多线程(五)--线程池的基本使用

一、线程池(ThreadPoolExecutor)的创建

     ThreadPoolExecutor内部的构造函数只有四种

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }


 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

   关于这些每个变量名的具体含义可以在上一篇线程池的基本介绍中看到 

   https://www.cnblogs.com/qqwhsj/p/10642918.html

   通过这四种构造函数我们可以得知:在创建线程池时必须有的参数为:CorePoolSize,maxmumPoolSize,KeepAliveTime,Unit,workQueue。且必须按照一定顺序。

   可以自定义加入的是threadFactory,handler。如果你不加入,线程会通过Executors工具类默认一个线程工厂,生成一个default_handler。

二、Executors类

   Executor是一种强大的线程池操作类,主要还有生成默认的线程工厂以及常见的四种线程池的创建方法,该方法都会返回一个ExecutorService对象。

   当然这四种创建方法本质还是使用super调用了ThreadPoolExecutor类中的构造方法,只是将构造方法中必须写入的corePoolSize等数据使用默认值。

   常见的四种线程池创建方法:

   1.SingleThreadPool:单线程化线程池,在这种线程池中,只会有一个线程的存在,将所有的任务都放置于任务池,当线程执行完一个任务后,下一个任务继续当前线程执行。

public class ExecutorsTest {
    static int a=10;
    public static void main(String[]args){
        ExecutorService singlems= Executors.newSingleThreadExecutor();
        for(int i=0;i<100;i++){
            singlems.execute(
                    //将每个Runnable作为一个任务执行,无需产生多个线程
                    new Runnable() {
                        @Override
                        public void run() {
                              System.out.println(a);
                              try {
                                  Thread.sleep(1000);
                              }catch (InterruptedException ie){
                                  System.out.println("程序产生中断异常");
                              }
                        }
                    }
            );
        }
    }
}

2.CachedThreadPool,创建一个缓存线程池,当任务进入时线程会创建;若没有任务,则线程会直接销毁。当需要是会再次创建。

public class ExecutorsTest {
    static int a=10;
    public static void main(String[]args){
        ExecutorService singlems= Executors.newCachedThreadPool();
        for(int i=0;i<20;i++){
            try{
                Thread.sleep(2000);
            }catch(InterruptedException ie){
                ie.printStackTrace();
            }
            singlems.execute(
                    //将每个Runnable作为一个任务执行,无需产生多个线程
                    new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(Thread.currentThread().getName()+":输出");
                        }
                    }
            );
        }
    }
}

运行结果为:

pool-1-thread-1:输出
pool-1-thread-1:输出
pool-1-thread-1:输出
pool-1-thread-1:输出
pool-1-thread-1:输出
pool-1-thread-1:输出

3.FixedThreadPool,设置固定线程数目的线程池,每有一个任务时则会创建新的线程,但最大数目必须是你设置的最大数目。当正在运行的线程数目等于你设置的最大数目后,所有人任务都会防止与任务池中等待调用:

public class ExecutorsTest {
    static int a=10;
    public static void main(String[]args){
        ExecutorService singlems= Executors.newFixedThreadPool(3);
        for(int i=0;i<20;i++){

            singlems.execute(
                    //将每个Runnable作为一个任务执行,无需产生多个线程
                    new Runnable() {
                        @Override
                        public void run() {
                            try{
                                Thread.sleep(1000);
                            }catch(InterruptedException ie){
                                ie.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName()+":输出");
                        }
                    }
            );
        }
    }
}

执行结果为:

pool-1-thread-1:输出
pool-1-thread-3:输出
pool-1-thread-2:输出
pool-1-thread-1:输出
pool-1-thread-3:输出
pool-1-thread-2:输出
pool-1-thread-1:输出
pool-1-thread-3:输出
pool-1-thread-2:输出
pool-1-thread-3:输出
pool-1-thread-1:输出
pool-1-thread-2:输出

4.ScheduledThreadPool:支持定时或者周期性执行任务,但是返回都是ScheduledExecutorService,也需要设置核心线程数量。

   下面是执行延迟三秒,每五秒钟执行一次的代码:

public class ExecutorsTest {
    static int a=10;
    public static void main(String[]args){
        ScheduledExecutorService singlems= Executors.newScheduledThreadPool(3);
        for(int i=0;i<3;i++){

            singlems.scheduleAtFixedRate(
                    //将每个Runnable作为一个任务执行,无需产生多个线程
                    new Runnable() {
                        @Override
                        public void run() {
                            try{
                                Thread.sleep(1000);
                            }catch(InterruptedException ie){
                                ie.printStackTrace();
                            }
                            System.out.println(Thread.currentThread().getName()+":输出");
                        }
                    },3, 5,TimeUnit.SECONDS);
        }
    }
}

执行结果为:

pool-1-thread-2:输出
pool-1-thread-1:输出
pool-1-thread-3:输出
pool-1-thread-2:输出
pool-1-thread-1:输出
pool-1-thread-3:输出
原文地址:https://www.cnblogs.com/qqwhsj/p/10643796.html