5.ThreadPoolExecutor详解

总有人问线程池的问题 ?

于是就 专门写一篇,来讲讲 ThreadPoolExecutor

一、基础类和参数说明

/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    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.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

1.corePoolSize:该线程池中核心线程数最大值

2.maximumPoolSize: 该线程池中线程总数最大值

3.keepAliveTime:该线程池中非核心线程闲置超时时长,过了这个时间会被回收,并且不会再被创建出来。

4.unit:keepAliveTime的单位

5.workQueue:阻塞队列BlockingQueue,维护着等待执行的Runnable对象

workQueue有4中类型:常用的有ArrayBlockingQueue和LinkedBlockingQueue,后两种基本不用。

5.1ArrayBlockingQueue:基于数组结构的有界阻塞队列,构造函数一定要传大小,FIFO(先进先出);

5.2LinkedBlockingQueue:无界,默认大小65536(Integer.MAX_VALUE),当大量请求任务时,容易造成内存耗尽。5.3SynchronousQueue:同步队列,是一个特殊的BlockingQueue,它没有容量(这是因为在SynchronousQueue中,插入将等待另一个线程的删除操作,反之亦然)。具体可以参考:《Java SynchronousQueue Examples(译)》

4.4PriorityBlockingQueue: 优先队列,无界。

5.5 DelayedWorkQueue:这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务阻塞队列常见的方法如下表所示:

6.threadFactory:创建线程的接口,需要实现他的Thread newThread(Runnable r)方法。

7.RejectedExecutionHandler:饱和策略,最大线程和工作队列容量且已经饱和时execute方法都将调用RejectedExecutionHandler 

二、工作方式(结论)

workQueue 选择不同,处理方式也不同,只列举出来两个常用的

workQueue方式情景条件处理方式
ArrayBlockingQueue

1.任务数<=核心线程数corePoolSize

 

2.maximumPoolSize>=任务数>核心线程数corePoolSize

2.1

任务数<=核心线程数corePoolSize + ArrayBlockingQueue指定长度

 

2.2 任务数>核心线程数corePoolSize + ArrayBlockingQueue指定长度

 

3.任务数>maximumPoolSize

 

 

1.直接用核心线程执行

2.1 使用核心线程数,超出部分放到队列中等待顺序执行

2.2 已经超出了队列长度的部分,新建线程执行,最终将线程数最大扩容到maximumPoolSize这个等级,此时同时运行的线程最多有maximumPoolSize个线程在运行

3.如果瞬间加入的任务数大于maximumPoolSize,则超出部分会执行饱和策略,默认为拒绝抛异常

LinkedBlockingQueue

任务数小于、大于、等于核心线程数corePoolSize

 

由于队列无界,所以处理方式相对简单:最多用核心线程数corePoolSize个线程执行任务,超过的任务放入LinkedBlockingQueue队列中,等待核心线程释放资源后,排队执行

 

三、测试代码

package com;

import com.google.common.util.concurrent.ThreadFactoryBuilder;


import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;

public class ThreadPoolTest {

    private static Executor executor = null;
    //线程池缓冲队列
    private static LinkedBlockingQueue<Runnable> workQueue = null;
    //当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中
    private static  int COREPOOLSIZE = 2;
    // 最多有这么多个线程,使用ArrayBlockingQueue阻塞队列时,这个值会生效
    private static  int MAXIMUMPOOLSIZE = 3;


    public static void main(String[] args) throws InterruptedException {
        //一下为执行例子,执行结果在具体方法中

        //1.向线程池中添加任务,当任务数量少于corePoolSize时,会自动创建thead来处理这些任务;
        testLtCorePoolSize();
        //2.当添加任务数大于COREPOOLSIZE且少于MAXIMUMPOOLSIZE时,MAXIMUMPOOLSIZE参数理论上会失效。。
        //   2.1如果创建的workQueue是为LinkedBlockingQueue(无需指定长度,自动扩容,但是实际使用过程中有可能会内存溢出)类型
        //      2.1.1当添加任务数大于COREPOOLSIZE且少于MAXIMUMPOOLSIZE时,会把这些任务放到workQueue,等待执行
        testLinkedBlockingQueueGtCorePoolSizeAndLtMaximumpoolize();
        //      2.1.2 当添加任务数大于MAXIMUMPOOLSIZE时,会把这些任务放到workQueue,等待执行,跟2.1中没啥区别。
        testLinkedBlockingQueueGtMaximumpoolize();
        //   2.2如果创建的workQueue是为ArrayBlockingQueue类型(这个类型的队列必须指定长度)
        //      2.2.1如果(任务数N)-COREPOOLSIZE <= ArrayBlockingQueue的指定长度,情况与2.1.1相同,等待执行即可(这个没有例子看,跟2.1.1,2.2.2一样的,没啥区别)

        //      2.2.2(任务数N)-COREPOOLSIZE > ArrayBlockingQueue的指定长度,会新创建(任务数N)-COREPOOLSIZE个线程进行执行;
        testArrayBlockingQueueGtBlockQueueSizeAndLtMaximumpoolsize();
        //3.任务数>MAXIMUMPOOLSIZE,
        //  3.1workQueue是ArrayBlockingQueue类型的,都会根据拒绝策略进行处理,默认是抛异常,拒绝
        testArrayBlockingQueueGtMaximumpoolsize();
        //  3.2workQueue是LinkedBlockingQueue类型的,这个会放到缓冲队列中,,默默消费,不会报异常的
        testLinkedBlockingQueueGtMaximumpoolsize();

        //任务数>MAXIMUMPOOLSIZE workQueue是ArrayBlockingQueue类型的,我们测试下keepAliveTime参数是干嘛的
        // 结论是  任务数>COREPOOLSIZE  之后的创建的MAXIMUMPOOLSIZE-COREPOOLSIZE这些线程相当于是借的,如果空闲等待时间超过keepAliveTime,会直接被回收。这些线程相当于是借的,还了就没了,以后不会再创建了
          
        testArrayBlockingQueueAliveTime();




    }


    /**
     *
     *
     */
    private static void testLtCorePoolSize() throws InterruptedException {
        workQueue = new LinkedBlockingQueue<>();
        executor = new ThreadPoolExecutor(COREPOOLSIZE,
                MAXIMUMPOOLSIZE,
                60,
                TimeUnit.SECONDS,
                workQueue,
                new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ThreadPoolTest-%d").build());
        for (int i = 0;i< COREPOOLSIZE; i ++) {
            executor.execute(new TestThread(1000));
        }

        //  主线程休眠10s以观察情况
        Thread.sleep(10000);
        // 以下为这个方法运行完的结果,我们可以得出结论:
        // 向线程池中添加任务,当任务数量少于corePoolSize时,会自动创建thead来处理这些任务;
        /**
         * 2020-06-18 18:17:55.27线程ThreadPoolTest-0启动
         * 2020-06-18 18:17:55.27线程ThreadPoolTest-1启动
         * 2020-06-18 18:17:55.28线程ThreadPoolTest-1执行中进行1阶段
         * 2020-06-18 18:17:55.28线程ThreadPoolTest-0执行中进行1阶段
         * 2020-06-18 18:17:55.230线程ThreadPoolTest-0执行中进行2阶段
         * 2020-06-18 18:17:55.230线程ThreadPoolTest-1执行中进行2阶段
         * 2020-06-18 18:17:55.431线程ThreadPoolTest-0执行中进行3阶段
         * 2020-06-18 18:17:55.431线程ThreadPoolTest-1执行中进行3阶段
         * 2020-06-18 18:17:55.634线程ThreadPoolTest-1执行中进行4阶段
         * 2020-06-18 18:17:55.634线程ThreadPoolTest-0执行中进行4阶段
         * 2020-06-18 18:17:55.838线程ThreadPoolTest-0执行中进行5阶段
         * 2020-06-18 18:17:55.838线程ThreadPoolTest-1执行中进行5阶段
         * 2020-06-18 18:17:56.42线程ThreadPoolTest-1结束
         * 2020-06-18 18:17:56.42线程ThreadPoolTest-0结束
         */
    }

    /**
     * 2.1.1 当添加任务数大于COREPOOLSIZE且少于MAXIMUMPOOLSIZE时,MAXIMUMPOOLSIZE参数理论上会失效。。
     * 如果创建的workQueue是为LinkedBlockingQueue(无需指定长度,自动扩容,但是实际使用过程中有可能会内存溢出)类型,会把这些任务放到workQueue,等待执行
     * @throws InterruptedException
     */
    private static void testLinkedBlockingQueueGtCorePoolSizeAndLtMaximumpoolize() throws InterruptedException {
        workQueue = new LinkedBlockingQueue<>();
        COREPOOLSIZE = 2;
        MAXIMUMPOOLSIZE  = 4;
        executor = new ThreadPoolExecutor(COREPOOLSIZE,
                MAXIMUMPOOLSIZE,
                60,
                TimeUnit.SECONDS,
                workQueue,
                new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ThreadPoolTest-%d").build());
        for (int i = 0; i < MAXIMUMPOOLSIZE; i++) {
            executor.execute(new TestThread(1000));
        }

        //  主线程休眠10s以观察情况
        Thread.sleep(10000);
        /**
         *   以下为这个方法运行完的结果,
         * 2020-06-18 18:29:30.517线程ThreadPoolTest-0启动
         * 2020-06-18 18:29:30.517线程ThreadPoolTest-1启动
         * 2020-06-18 18:29:30.518线程ThreadPoolTest-0执行中进行1阶段
         * 2020-06-18 18:29:30.518线程ThreadPoolTest-1执行中进行1阶段
         * 2020-06-18 18:29:30.722线程ThreadPoolTest-1执行中进行2阶段
         * 2020-06-18 18:29:30.722线程ThreadPoolTest-0执行中进行2阶段
         * 2020-06-18 18:29:30.924线程ThreadPoolTest-1执行中进行3阶段
         * 2020-06-18 18:29:30.924线程ThreadPoolTest-0执行中进行3阶段
         * 2020-06-18 18:29:31.126线程ThreadPoolTest-1执行中进行4阶段
         * 2020-06-18 18:29:31.126线程ThreadPoolTest-0执行中进行4阶段
         * 2020-06-18 18:29:31.330线程ThreadPoolTest-0执行中进行5阶段
         * 2020-06-18 18:29:31.330线程ThreadPoolTest-1执行中进行5阶段
         * 2020-06-18 18:29:31.533线程ThreadPoolTest-0结束
         * 2020-06-18 18:29:31.533线程ThreadPoolTest-1结束
         *
         * 注意看 下面的线程名字根本没有发生变化,所以并没有创建新的线程,而是复用了 ThreadPoolTest-0 -1线程
         * 2020-06-18 18:29:31.533线程ThreadPoolTest-0启动
         * 2020-06-18 18:29:31.533线程ThreadPoolTest-1启动
         * 2020-06-18 18:29:31.533线程ThreadPoolTest-0执行中进行1阶段
         * 2020-06-18 18:29:31.533线程ThreadPoolTest-1执行中进行1阶段
         * 2020-06-18 18:29:31.735线程ThreadPoolTest-1执行中进行2阶段
         * 2020-06-18 18:29:31.735线程ThreadPoolTest-0执行中进行2阶段
         * 2020-06-18 18:29:31.937线程ThreadPoolTest-0执行中进行3阶段
         * 2020-06-18 18:29:31.938线程ThreadPoolTest-1执行中进行3阶段
         * 2020-06-18 18:29:32.139线程ThreadPoolTest-1执行中进行4阶段
         * 2020-06-18 18:29:32.139线程ThreadPoolTest-0执行中进行4阶段
         * 2020-06-18 18:29:32.344线程ThreadPoolTest-0执行中进行5阶段
         * 2020-06-18 18:29:32.344线程ThreadPoolTest-1执行中进行5阶段
         * 2020-06-18 18:29:32.544线程ThreadPoolTest-1结束
         * 2020-06-18 18:29:32.544线程ThreadPoolTest-0结束
         */
    }
    /**
     * 2.1.2 当添加任务数大于MAXIMUMPOOLSIZE时,MAXIMUMPOOLSIZE参数理论上会失效。。
     * 如果创建的workQueue是为LinkedBlockingQueue类型,会把这些任务放到workQueue,等待执行,跟2.1中没啥区别。。
     * @throws InterruptedException
     */
    private static void testLinkedBlockingQueueGtMaximumpoolize() throws InterruptedException {
        workQueue = new LinkedBlockingQueue<>();
        COREPOOLSIZE = 2;
        MAXIMUMPOOLSIZE  = 4;
        executor = new ThreadPoolExecutor(COREPOOLSIZE,
                MAXIMUMPOOLSIZE,
                60,
                TimeUnit.SECONDS,
                workQueue,
                new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ThreadPoolTest-%d").build());
        for (int i = 0; i < MAXIMUMPOOLSIZE + 2; i++) {
            executor.execute(new TestThread(1000));
        }

        //  主线程休眠10s以观察情况
        Thread.sleep(10000);
        /**
         *   以下为这个方法运行完的结果,
         2020-06-18 20:41:32.384线程ThreadPoolTest-1启动
         2020-06-18 20:41:32.384线程ThreadPoolTest-0启动
         2020-06-18 20:41:32.385线程ThreadPoolTest-1执行中进行1阶段
         2020-06-18 20:41:32.385线程ThreadPoolTest-0执行中进行1阶段
         2020-06-18 20:41:32.588线程ThreadPoolTest-1执行中进行2阶段
         2020-06-18 20:41:32.588线程ThreadPoolTest-0执行中进行2阶段
         2020-06-18 20:41:32.791线程ThreadPoolTest-1执行中进行3阶段
         2020-06-18 20:41:32.791线程ThreadPoolTest-0执行中进行3阶段
         2020-06-18 20:41:32.994线程ThreadPoolTest-1执行中进行4阶段
         2020-06-18 20:41:32.994线程ThreadPoolTest-0执行中进行4阶段
         2020-06-18 20:41:33.198线程ThreadPoolTest-0执行中进行5阶段
         2020-06-18 20:41:33.198线程ThreadPoolTest-1执行中进行5阶段
         2020-06-18 20:41:33.399线程ThreadPoolTest-0结束
         2020-06-18 20:41:33.399线程ThreadPoolTest-1结束

         安安静静的等待核心的两个线程执行完,然后开启下一轮切换
         2020-06-18 20:41:33.400线程ThreadPoolTest-1启动
         2020-06-18 20:41:33.400线程ThreadPoolTest-0启动
         2020-06-18 20:41:33.400线程ThreadPoolTest-1执行中进行1阶段
         2020-06-18 20:41:33.400线程ThreadPoolTest-0执行中进行1阶段
         2020-06-18 20:41:33.603线程ThreadPoolTest-1执行中进行2阶段
         2020-06-18 20:41:33.604线程ThreadPoolTest-0执行中进行2阶段
         2020-06-18 20:41:33.805线程ThreadPoolTest-0执行中进行3阶段
         2020-06-18 20:41:33.805线程ThreadPoolTest-1执行中进行3阶段
         2020-06-18 20:41:34.8线程ThreadPoolTest-0执行中进行4阶段
         2020-06-18 20:41:34.8线程ThreadPoolTest-1执行中进行4阶段
         2020-06-18 20:41:34.213线程ThreadPoolTest-1执行中进行5阶段
         2020-06-18 20:41:34.213线程ThreadPoolTest-0执行中进行5阶段
         2020-06-18 20:41:34.414线程ThreadPoolTest-1结束
         2020-06-18 20:41:34.414线程ThreadPoolTest-0结束

         安安静静的等待核心的两个线程执行完,然后开启下一轮切换
         2020-06-18 20:41:34.414线程ThreadPoolTest-1启动
         2020-06-18 20:41:34.414线程ThreadPoolTest-0启动
         2020-06-18 20:41:34.415线程ThreadPoolTest-1执行中进行1阶段
         2020-06-18 20:41:34.415线程ThreadPoolTest-0执行中进行1阶段
         2020-06-18 20:41:34.619线程ThreadPoolTest-1执行中进行2阶段
         2020-06-18 20:41:34.619线程ThreadPoolTest-0执行中进行2阶段
         2020-06-18 20:41:34.823线程ThreadPoolTest-0执行中进行3阶段
         2020-06-18 20:41:34.823线程ThreadPoolTest-1执行中进行3阶段
         2020-06-18 20:41:35.27线程ThreadPoolTest-0执行中进行4阶段
         2020-06-18 20:41:35.27线程ThreadPoolTest-1执行中进行4阶段
         2020-06-18 20:41:35.230线程ThreadPoolTest-0执行中进行5阶段
         2020-06-18 20:41:35.230线程ThreadPoolTest-1执行中进行5阶段
         2020-06-18 20:41:35.432线程ThreadPoolTest-0结束
         2020-06-18 20:41:35.432线程ThreadPoolTest-1结束
         */
    }

    /**
     * 2.2当添加(任务数N)大于COREPOOLSIZE且少于MAXIMUMPOOLSIZE,
     * 如果创建的workQueue是为ArrayBlockingQueue类型(这个类型的队列必须指定长度),
     * 2.2.1如果(任务数N)-COREPOOLSIZE <= ArrayBlockingQueue的指定长度,情况与2.1.1相同,等待执行即可
     * 2.2.2(任务数N)-COREPOOLSIZE > ArrayBlockingQueue的指定长度,会新创建(任务数N)-COREPOOLSIZE个线程进行执行;
     *
     * 这个测试方法就只是实现2.2.2而已
     * @throws InterruptedException
     */
    private static void testArrayBlockingQueueGtBlockQueueSizeAndLtMaximumpoolsize() throws InterruptedException {
        // 设置阻塞队列,并且限定长度,从而触发创建thread的操作
        ArrayBlockingQueue workQueue = new ArrayBlockingQueue<Integer>(1);
        COREPOOLSIZE = 2;
        MAXIMUMPOOLSIZE  = 6;
        executor = new ThreadPoolExecutor(COREPOOLSIZE,
                MAXIMUMPOOLSIZE,
                60,
                TimeUnit.SECONDS,
                workQueue,
                new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ThreadPoolTest-%d").build());
        for (int i = 0; i < 5; i++) {
            // sleep一下看的结果更加明显
            Thread.sleep(20);
            executor.execute(new TestThread(1000));
        }
        //  主线程休眠10s以观察情况
        Thread.sleep(10000);
        /**
         * 一共有5个线程,2个核心线程ThreadPoolTest-0-1在执行,1个放到了workQueue阻塞队列里,由于阻塞队里满了,
         * 所以2个又直接启动了线程ThreadPoolTest-2,ThreadPoolTest-3执行。
         *
         2020-06-18 21:10:27.568线程ThreadPoolTest-0启动
         2020-06-18 21:10:27.568线程ThreadPoolTest-0执行中进行1阶段
         2020-06-18 21:10:27.591线程ThreadPoolTest-1启动
         2020-06-18 21:10:27.591线程ThreadPoolTest-1执行中进行1阶段
         2020-06-18 21:10:27.637线程ThreadPoolTest-2启动
         2020-06-18 21:10:27.638线程ThreadPoolTest-2执行中进行1阶段
         2020-06-18 21:10:27.660线程ThreadPoolTest-3启动
         2020-06-18 21:10:27.660线程ThreadPoolTest-3执行中进行1阶段
         2020-06-18 21:10:27.771线程ThreadPoolTest-0执行中进行2阶段
         2020-06-18 21:10:27.794线程ThreadPoolTest-1执行中进行2阶段
         2020-06-18 21:10:27.842线程ThreadPoolTest-2执行中进行2阶段
         2020-06-18 21:10:27.861线程ThreadPoolTest-3执行中进行2阶段
         2020-06-18 21:10:27.972线程ThreadPoolTest-0执行中进行3阶段
         2020-06-18 21:10:27.995线程ThreadPoolTest-1执行中进行3阶段
         2020-06-18 21:10:28.44线程ThreadPoolTest-2执行中进行3阶段
         2020-06-18 21:10:28.64线程ThreadPoolTest-3执行中进行3阶段
         2020-06-18 21:10:28.175线程ThreadPoolTest-0执行中进行4阶段
         2020-06-18 21:10:28.196线程ThreadPoolTest-1执行中进行4阶段
         2020-06-18 21:10:28.248线程ThreadPoolTest-2执行中进行4阶段
         2020-06-18 21:10:28.268线程ThreadPoolTest-3执行中进行4阶段
         2020-06-18 21:10:28.382线程ThreadPoolTest-0执行中进行5阶段
         2020-06-18 21:10:28.401线程ThreadPoolTest-1执行中进行5阶段
         2020-06-18 21:10:28.450线程ThreadPoolTest-2执行中进行5阶段
         2020-06-18 21:10:28.470线程ThreadPoolTest-3执行中进行5阶段
         2020-06-18 21:10:28.586线程ThreadPoolTest-0结束
         2020-06-18 21:10:28.586线程ThreadPoolTest-0启动
         2020-06-18 21:10:28.586线程ThreadPoolTest-0执行中进行1阶段
         2020-06-18 21:10:28.602线程ThreadPoolTest-1结束
         2020-06-18 21:10:28.654线程ThreadPoolTest-2结束
         2020-06-18 21:10:28.671线程ThreadPoolTest-3结束

         workQueue阻塞队列里的那个等核心线程结束了任务,就重新放进去执行。
         2020-06-18 21:10:28.791线程ThreadPoolTest-0执行中进行2阶段
         2020-06-18 21:10:28.997线程ThreadPoolTest-0执行中进行3阶段
         2020-06-18 21:10:29.199线程ThreadPoolTest-0执行中进行4阶段
         2020-06-18 21:10:29.404线程ThreadPoolTest-0执行中进行5阶段
         2020-06-18 21:10:29.609线程ThreadPoolTest-0结束
         */
    }

    /**
     * 3.任务数>MAXIMUMPOOLSIZE,
     * 3.1workQueue是ArrayBlockingQueue类型的,都会根据拒绝策略进行处理,默认是抛异常,拒绝
     */
    private static void testArrayBlockingQueueGtMaximumpoolsize() throws InterruptedException {
        ArrayBlockingQueue workQueue = new ArrayBlockingQueue<Integer>(1);
        COREPOOLSIZE = 2;
        MAXIMUMPOOLSIZE  = 2;
        executor = new ThreadPoolExecutor(COREPOOLSIZE,
                MAXIMUMPOOLSIZE,
                60,
                TimeUnit.SECONDS,
                workQueue,
                new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ThreadPoolTest-%d").build());
        for (int i = 0; i < MAXIMUMPOOLSIZE +2; i++) {
            try {
                executor.execute(new TestThread(1000));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //  主线程休眠10s以观察情况
        Thread.sleep(10000);
        /**
         *
         2020-06-18 21:20:16.787线程ThreadPoolTest-0启动
         2020-06-18 21:20:16.787线程ThreadPoolTest-1启动
         2020-06-18 21:20:16.788线程ThreadPoolTest-0执行中进行1阶段
         2020-06-18 21:20:16.788线程ThreadPoolTest-1执行中进行1阶段
         超过了
         java.util.concurrent.RejectedExecutionException: Task com.qlchat.ThreadPoolTest$TestThread@4ddced80 rejected from java.util.concurrent.ThreadPoolExecutor@1534f01b[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0]
         at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
         at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
         at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
         at com.qlchat.ThreadPoolTest.testGtMaximumpoolsize(ThreadPoolTest.java:288)
         at com.qlchat.ThreadPoolTest.main(ThreadPoolTest.java:34)
         2020-06-18 21:20:16.989线程ThreadPoolTest-1执行中进行2阶段
         2020-06-18 21:20:16.989线程ThreadPoolTest-0执行中进行2阶段
         2020-06-18 21:20:17.194线程ThreadPoolTest-0执行中进行3阶段
         2020-06-18 21:20:17.194线程ThreadPoolTest-1执行中进行3阶段
         2020-06-18 21:20:17.398线程ThreadPoolTest-1执行中进行4阶段
         2020-06-18 21:20:17.398线程ThreadPoolTest-0执行中进行4阶段
         2020-06-18 21:20:17.599线程ThreadPoolTest-1执行中进行5阶段
         2020-06-18 21:20:17.599线程ThreadPoolTest-0执行中进行5阶段
         2020-06-18 21:20:17.802线程ThreadPoolTest-0结束
         2020-06-18 21:20:17.802线程ThreadPoolTest-1结束
         2020-06-18 21:20:17.802线程ThreadPoolTest-0启动
         2020-06-18 21:20:17.803线程ThreadPoolTest-0执行中进行1阶段
         2020-06-18 21:20:18.5线程ThreadPoolTest-0执行中进行2阶段
         2020-06-18 21:20:18.211线程ThreadPoolTest-0执行中进行3阶段
         2020-06-18 21:20:18.412线程ThreadPoolTest-0执行中进行4阶段
         2020-06-18 21:20:18.617线程ThreadPoolTest-0执行中进行5阶段
         2020-06-18 21:20:18.821线程ThreadPoolTest-0结束
         */
    }
    /**
     * 3.任务数>MAXIMUMPOOLSIZE,
     * 3.2workQueue是LinkedBlockingQueue类型的,这个会放到缓冲队列中,,默默消费,不会报异常的
     */
    private static void testLinkedBlockingQueueGtMaximumpoolsize() throws InterruptedException {
        LinkedBlockingQueue workQueue = new LinkedBlockingQueue<>();
        COREPOOLSIZE = 2;
        MAXIMUMPOOLSIZE  = 2;
        executor = new ThreadPoolExecutor(COREPOOLSIZE,
                MAXIMUMPOOLSIZE,
                60,
                TimeUnit.SECONDS,
                workQueue,
                new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ThreadPoolTest-%d").build());
        for (int i = 0; i < MAXIMUMPOOLSIZE +2; i++) {
            try {
                executor.execute(new TestThread(1000));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //  主线程休眠10s以观察情况
        Thread.sleep(10000);
        /**
         * 2020-06-18 21:24:20.731线程ThreadPoolTest-1启动
         * 2020-06-18 21:24:20.731线程ThreadPoolTest-0启动
         * 2020-06-18 21:24:20.732线程ThreadPoolTest-0执行中进行1阶段
         * 2020-06-18 21:24:20.732线程ThreadPoolTest-1执行中进行1阶段
         * 2020-06-18 21:24:20.932线程ThreadPoolTest-0执行中进行2阶段
         * 2020-06-18 21:24:20.936线程ThreadPoolTest-1执行中进行2阶段
         * 2020-06-18 21:24:21.135线程ThreadPoolTest-0执行中进行3阶段
         * 2020-06-18 21:24:21.140线程ThreadPoolTest-1执行中进行3阶段
         * 2020-06-18 21:24:21.338线程ThreadPoolTest-0执行中进行4阶段
         * 2020-06-18 21:24:21.346线程ThreadPoolTest-1执行中进行4阶段
         * 2020-06-18 21:24:21.543线程ThreadPoolTest-0执行中进行5阶段
         * 2020-06-18 21:24:21.550线程ThreadPoolTest-1执行中进行5阶段
         * 2020-06-18 21:24:21.744线程ThreadPoolTest-0结束
         * 2020-06-18 21:24:21.744线程ThreadPoolTest-0启动
         * 2020-06-18 21:24:21.745线程ThreadPoolTest-0执行中进行1阶段
         * 2020-06-18 21:24:21.754线程ThreadPoolTest-1结束
         * 2020-06-18 21:24:21.755线程ThreadPoolTest-1启动
         * 2020-06-18 21:24:21.756线程ThreadPoolTest-1执行中进行1阶段
         * 2020-06-18 21:24:21.950线程ThreadPoolTest-0执行中进行2阶段
         * 2020-06-18 21:24:21.962线程ThreadPoolTest-1执行中进行2阶段
         * 2020-06-18 21:24:22.154线程ThreadPoolTest-0执行中进行3阶段
         * 2020-06-18 21:24:22.164线程ThreadPoolTest-1执行中进行3阶段
         * 2020-06-18 21:24:22.356线程ThreadPoolTest-0执行中进行4阶段
         * 2020-06-18 21:24:22.367线程ThreadPoolTest-1执行中进行4阶段
         * 2020-06-18 21:24:22.561线程ThreadPoolTest-0执行中进行5阶段
         * 2020-06-18 21:24:22.572线程ThreadPoolTest-1执行中进行5阶段
         * 2020-06-18 21:24:22.766线程ThreadPoolTest-0结束
         * 2020-06-18 21:24:22.777线程ThreadPoolTest-1结束
         */
    }

    /**
     * 4.任务数>MAXIMUMPOOLSIZEworkQueue是ArrayBlockingQueue类型的,我们测试下keepAliveTime参数是干嘛的
     */
    private static void testArrayBlockingQueueAliveTime() throws InterruptedException {
        ArrayBlockingQueue workQueue = new ArrayBlockingQueue<Integer>(1);
        COREPOOLSIZE = 2;
        MAXIMUMPOOLSIZE = 4;
        executor = new ThreadPoolExecutor(COREPOOLSIZE,
                MAXIMUMPOOLSIZE,
                10,
                TimeUnit.MILLISECONDS,
                workQueue,
                new ThreadFactoryBuilder().setDaemon(true).setNameFormat("ThreadPoolTest-%d").build());
        for (int i = 0; i < COREPOOLSIZE; i++) {
            try {
                executor.execute(new TestThread(5000, "coreThread" + i));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        for (int i = 0; i < 1; i++) {
            try {
                executor.execute(new TestThread(5000, "workQueueThread" + i));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        for (int i = 0; i < 4; i++) {
            try {
                Thread.sleep(100);
                System.out.println(getNow() + "put maximumpoolThread" + i);
                executor.execute(new TestThread(20, "maximumpoolThread" + i));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //  主线程休眠10s以观察情况
        Thread.sleep(20000);
        /**
         * 2020-06-19 10:15:28.878线程ThreadPoolTest-1:coreThread1启动
         * 2020-06-19 10:15:28.878线程ThreadPoolTest-0:coreThread0启动
         * 2020-06-19 10:15:28.884线程ThreadPoolTest-1:coreThread1执行中进行1阶段
         * 2020-06-19 10:15:28.884线程ThreadPoolTest-0:coreThread0执行中进行1阶段
         * 2020-06-19 10:15:28.963put maximumpoolThread0
         * 2020-06-19 10:15:28.964线程ThreadPoolTest-2:maximumpoolThread0启动
         * 2020-06-19 10:15:28.964线程ThreadPoolTest-2:maximumpoolThread0执行中进行1阶段
         * 2020-06-19 10:15:28.969线程ThreadPoolTest-2:maximumpoolThread0执行中进行2阶段
         * 2020-06-19 10:15:28.974线程ThreadPoolTest-2:maximumpoolThread0执行中进行3阶段
         * 2020-06-19 10:15:28.979线程ThreadPoolTest-2:maximumpoolThread0执行中进行4阶段
         * 2020-06-19 10:15:28.985线程ThreadPoolTest-2:maximumpoolThread0执行中进行5阶段
         * 2020-06-19 10:15:28.990线程ThreadPoolTest-2:maximumpoolThread0结束
         * 2020-06-19 10:15:28.990线程ThreadPoolTest-2:workQueueThread0启动
         * 2020-06-19 10:15:28.990线程ThreadPoolTest-2:workQueueThread0执行中进行1阶段
         * 2020-06-19 10:15:29.67put maximumpoolThread1
         * 2020-06-19 10:15:29.171put maximumpoolThread2
         * 2020-06-19 10:15:29.171线程ThreadPoolTest-3:maximumpoolThread2启动
         * 2020-06-19 10:15:29.172线程ThreadPoolTest-3:maximumpoolThread2执行中进行1阶段
         * 2020-06-19 10:15:29.177线程ThreadPoolTest-3:maximumpoolThread2执行中进行2阶段
         * 2020-06-19 10:15:29.183线程ThreadPoolTest-3:maximumpoolThread2执行中进行3阶段
         * 2020-06-19 10:15:29.188线程ThreadPoolTest-3:maximumpoolThread2执行中进行4阶段
         * 2020-06-19 10:15:29.193线程ThreadPoolTest-3:maximumpoolThread2执行中进行5阶段
         * 2020-06-19 10:15:29.198线程ThreadPoolTest-3:maximumpoolThread2结束
         * 2020-06-19 10:15:29.198线程ThreadPoolTest-3:maximumpoolThread1启动
         * 2020-06-19 10:15:29.199线程ThreadPoolTest-3:maximumpoolThread1执行中进行1阶段
         * 2020-06-19 10:15:29.204线程ThreadPoolTest-3:maximumpoolThread1执行中进行2阶段
         * 2020-06-19 10:15:29.209线程ThreadPoolTest-3:maximumpoolThread1执行中进行3阶段
         * 2020-06-19 10:15:29.214线程ThreadPoolTest-3:maximumpoolThread1执行中进行4阶段
         * 2020-06-19 10:15:29.219线程ThreadPoolTest-3:maximumpoolThread1执行中进行5阶段
         * 2020-06-19 10:15:29.224线程ThreadPoolTest-3:maximumpoolThread1结束
         *
         * 注意观察这里,put进去了maximumpoolThread3,但是由于ThreadPoolTest-3 过了keepAliveTime时间10ms,被回收了。
         * 所以就算put进去,,只能等到其他线程有空的时候执行
         * 2020-06-19 10:15:29.271put maximumpoolThread3

         * 2020-06-19 10:15:29.889线程ThreadPoolTest-1:coreThread1执行中进行2阶段
         * 2020-06-19 10:15:29.889线程ThreadPoolTest-0:coreThread0执行中进行2阶段
         * 2020-06-19 10:15:29.992线程ThreadPoolTest-2:workQueueThread0执行中进行2阶段
         * 2020-06-19 10:15:30.891线程ThreadPoolTest-0:coreThread0执行中进行3阶段
         * 2020-06-19 10:15:30.891线程ThreadPoolTest-1:coreThread1执行中进行3阶段
         * 2020-06-19 10:15:30.994线程ThreadPoolTest-2:workQueueThread0执行中进行3阶段
         * 2020-06-19 10:15:31.894线程ThreadPoolTest-0:coreThread0执行中进行4阶段
         * 2020-06-19 10:15:31.894线程ThreadPoolTest-1:coreThread1执行中进行4阶段
         * 2020-06-19 10:15:31.999线程ThreadPoolTest-2:workQueueThread0执行中进行4阶段
         * 2020-06-19 10:15:32.899线程ThreadPoolTest-0:coreThread0执行中进行5阶段
         * 2020-06-19 10:15:32.899线程ThreadPoolTest-1:coreThread1执行中进行5阶段
         * 2020-06-19 10:15:33.0线程ThreadPoolTest-2:workQueueThread0执行中进行5阶段
         * 2020-06-19 10:15:33.901线程ThreadPoolTest-0:coreThread0结束
         * 2020-06-19 10:15:33.901线程ThreadPoolTest-1:coreThread1结束
         * maximumpoolThread3被ThreadPoolTest-0 执行
         * 2020-06-19 10:15:33.901线程ThreadPoolTest-0:maximumpoolThread3启动
         * 2020-06-19 10:15:33.901线程ThreadPoolTest-0:maximumpoolThread3执行中进行1阶段
         * 2020-06-19 10:15:33.907线程ThreadPoolTest-0:maximumpoolThread3执行中进行2阶段
         * 2020-06-19 10:15:33.913线程ThreadPoolTest-0:maximumpoolThread3执行中进行3阶段
         * 2020-06-19 10:15:33.918线程ThreadPoolTest-0:maximumpoolThread3执行中进行4阶段
         * 2020-06-19 10:15:33.924线程ThreadPoolTest-0:maximumpoolThread3执行中进行5阶段
         * 2020-06-19 10:15:33.929线程ThreadPoolTest-0:maximumpoolThread3结束
         * 2020-06-19 10:15:34.1线程ThreadPoolTest-2:workQueueThread0结束
         */
    }
    static class TestThread implements Runnable {
        //执行时间,单位是毫秒
        private Integer runTime = null;
        //为了便于观察线程执行过程,分5次打印
        private Integer step =  5;

        private String name = null;


        public TestThread(Integer runTime, String name) {
            this.runTime = runTime;
            this.name = name;
        }


        public TestThread(Integer runTime) {
            this.runTime = runTime;
        }

        @Override
        public void run() {
            String threadName = name == null ? Thread.currentThread().getName() : Thread.currentThread().getName() + ":" + name;

            System.out.println(MessageFormat.format("{0}线程{1}启动",getNow(), threadName));
            try {
                for (int i = 0; i< step;i++) {
                    System.out.println(MessageFormat.format("{0}线程{1}执行中进行{2}阶段", getNow(), threadName, i+1));
                    Thread.sleep(runTime /step);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(MessageFormat.format("{0}线程{1}结束", getNow(),threadName));


        }

        public Integer getRunTime() {
            return runTime;
        }

        public void setRunTime(Integer runTime) {
            this.runTime = runTime;
        }


    }
    static String getNow() {
        DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
        return formatter.format(new Date());
    }


}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值