zoukankan      html  css  js  c++  java
  • java中线程池的使用方法

    1 引入线程池的原因

      由于线程的生命周期中包括创建、就绪、运行、阻塞、销毁阶段,当我们待处理的任务数目较小时,我们可以自己创建几个线程来处理相应的任务,但当有大量的任务时,由于创建、销毁线程需要很大的开销,运用线程池这些问题就大大的缓解了。

    2 线程池的使用

      我们只需要运用Executors类给我们提供的静态方法,就可以创建相应的线程池:

      public static ExecutorSevice newSingleThreadExecutor()

      public static ExecutorSevice newFixedThreadPool()

      public static ExecutorSevice  newCachedThreadPool()

      newSingleThreadExecutor返回以个包含单线程的Executor,将多个任务交给此Exector时,这个线程处理完一个任务后接着处理下一个任务,若该线程出现异常,将会有一个新的线程来替代。

      newFixedThreadPool返回一个包含指定数目线程的线程池,如果任务数量多于线程数目,那么没有没有执行的任务必须等待,直到有任务完成为止。

      newCachedThreadPool根据用户的任务数创建相应的线程来处理,该线程池不会对线程数目加以限制,完全依赖于JVM能创建线程的数量,可能引起内存不足。

      我们只需要将待执行的任务放入run方法中即可,将Runnable接口的实现类交给线程池的execute方法,作为它的一个参数,如下所示:

    Executor executor = Executors.newSingleThreadExecutor();
    executor.execute(new Runnable(){
        public void run(){
           //执行的任务    
      }
    }

      如果需要给任务传递参数,可以通过创建一个Runnable接口的实现类来完成。 

    3 线程池使用的示例

      下面我们通过一个实例来说明线程池的使用方法,该实例模仿子HADOOP中作业初始化过程,也即利用线程池从队列中取出作业并对作业进行初始化,其代码如下:

    package com.yueliming.ThreadPool;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class FixedThreadPool {
    
        public static List<Double> queue;
        public ExecutorService threadPool;
    
        public FixedThreadPool() {
            queue = new ArrayList<Double>();
            //产生一个 ExecutorService 对象,这个对象带有一个大小为 poolSize 的线程池,若任务数量大于 poolSize ,任务会被放在一个 queue 里顺序执行。 
            threadPool = Executors.newFixedThreadPool(5);
        }
    
        public static void main(String[] args) {
            FixedThreadPool outer = new FixedThreadPool();
            FixedThreadPool.Manager inner = outer.new Manager();
            Thread consumer = new Thread(inner);
    
            Thread producer = new Thread() {//用于向queue中放入数据
                public void run() {
                    while (true) {
                        synchronized (queue) {
                            double time = 1d;
                            long startTime = System.currentTimeMillis();
                            if (System.currentTimeMillis() - startTime >= time) {
                                startTime = System.currentTimeMillis();
                                for (int i = 0; i < 10; i++) {
                                    queue.add((Math.random() * 10000));
                                }
                                queue.notify();
                            }
                        }
                    }
                }
            };
            consumer.start();//启动守护线程,采用线程池来从queue中读取数据
            producer.start();
        }
    
        class Manager implements Runnable {
            int num = 0;
            public void run() {
                while (true) {
                    try {
                        synchronized (queue) {
                            System.out.println("队列的长度为:" + queue.size());
                            while (queue.isEmpty()) {
                                queue.wait();
                            }
                            double result = queue.remove(0);
                            num++;
                            System.out.println("成功从队列中取到数据!" + num);
                            threadPool.execute(new ExecutorThread(result));
                        }
                    } catch (InterruptedException t) {
                        break;
                    }
                }
                threadPool.shutdown();
            }
        }
    
        class ExecutorThread implements Runnable {
    
            private double value;
    
            public ExecutorThread(double value) {
                this.value = value;
            }
    
            public void run() {
                System.out.println("This is " + Thread.currentThread().getName() + " " + value);
            }
        }
    }
    View Code

      其中内部类Manager为一个线程负责从队列中获取作业,并交给线程池去处理任务,有一个线程专门将数据放入到队列中,也即每隔1ms向队列中放入10个数据。

  • 相关阅读:
    react.js
    shell if,case,for,while语法
    shell判断文件类型和权限
    shell编程之sed语法
    php魔术方法__SET __GET
    git 忽略文件.gitignore
    php设置错误,错误记录
    linux ifconfig显示 command not found
    数据库备份与恢复
    mysql主要技术
  • 原文地址:https://www.cnblogs.com/yueliming/p/3300587.html
Copyright © 2011-2022 走看看