什么是Executor框架?

        首先要了解什么是线程池?线程池是集中管理线程的,以实现线程的重用,降低资源消耗,提高响应速度,提高线程的可管理性等。线程用于执行异步任务,单个的线程既是工作单元也是执行机制,从JDK1.5开始,为了把工作单元与执行机制分离开,Executor框架诞生了,他是一个用于统一创建与运行的接口。Executor框架实现的就是线程池的功能。

ThreadPoolExecutor

线程池的真正实现类是 ThreadPoolExecutor,我们可以实现ThreadPoolExecutor 自定义线程池的方式,其次我们也可以使用Executor框架的 Executors类(java.util.concurrent包)创建封装好的线程。

而ThreadPoolExecutor 类参数最多,并且 Executors 封装的线程池底层都是基于ThreadPoolExecutor实现的。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

构造参数解释:

corePoolSize:核心线程数
 maximumPoolSize:最大线程数
 keepAliveTime:救急线程空闲时的最大生存时间
 unit:时间单位
 workQueue:阻塞队列(存放任务)
 PriorityBlockingQueue:优先队列
 threadFactory:线程工厂(给线程取名字)
 handler:拒绝策略

了解了底层的ThreadPoolExecutor后,以 Executors 封装线程池使用为例:

package com.example.redislock.threadpools;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        /**
         * 可重用固定线程数的线程池
         * 核心线程数=最大线程数
         * 无需超时时间,只需要设置核心线程数与threadFactory重命名线程即可
         * 使用 LinkedBlockingQueue 阻塞队列
         * 适用于任务量已知,相对耗时的任务
          */
        ExecutorService executorService = Executors.newFixedThreadPool(100, new ThreadFactory(){
            private AtomicInteger atomicInteger = new AtomicInteger(1);
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r,"myThread="+atomicInteger.getAndIncrement());
            }
        });

        /**
         * 根据需要创建新线程的线程池
         * 核心线程数为0,最大线程数为Integer.MAX_VALUE,所以全是救急线程
         * 生存时间为60秒,执行完毕自动释放
         * 队列使用 SynchronOusQueue,没有容量,相当于一手交钱一手交货.
         * 适合任务数比较密集,执行时间短的场景
         */
        ExecutorService executorService1 = Executors.newCachedThreadPool(new ThreadFactory() {
            private AtomicInteger atomicInteger = new AtomicInteger(1);
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "myThread=" + atomicInteger.getAndIncrement());
            }
        });

        /**
         * 使用单个worker线程的线程池
         * 多个任务排队进行,线程数为 1 ,任务超过 1 时,放入无界队列中
         * 队列使用 LinkedBlockingQueue
         * 任务执行完也不会释放,需要手动释放.
         * 任务执行失败没有补救措施,不可再用
         */
        ExecutorService executorService2 = Executors.newSingleThreadExecutor(new ThreadFactory() {
            private AtomicInteger atomicInteger = new AtomicInteger(1);
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r, "myThread=" + atomicInteger.getAndIncrement());
            }
        });

        for (int i=0;i<21;i++){
            executorService.execute(() -> {
                System.out.println("ThreadName = "+Thread.currentThread().getName());
            });
        }

        //线程状态变为 stop,不会再接收新任务,将队列中的任务返回,
        // 并使用interrupt方法中断正在执行的任务,相当于全部任务中断.
        executorService.shutdownNow();
        //线程状态变为 shutdown,不会再接收新任务,但等待队列和已提交的任务会执行完.
        executorService2.shutdown();

    }
}

根据对应输出结果理解线程池:

newFixedThreadPool:固定100个线程数量,20个线程并发执行:

ThreadName = myThread=1
ThreadName = myThread=3
ThreadName = myThread=2
ThreadName = myThread=4
ThreadName = myThread=5
ThreadName = myThread=11
ThreadName = myThread=6
ThreadName = myThread=12
ThreadName = myThread=9
ThreadName = myThread=10
ThreadName = myThread=7
ThreadName = myThread=8
ThreadName = myThread=13
ThreadName = myThread=14
ThreadName = myThread=15
ThreadName = myThread=16
ThreadName = myThread=17
ThreadName = myThread=18
ThreadName = myThread=19
ThreadName = myThread=20
ThreadName = myThread=21

newCachedThreadPool:20个任务量,但是只有12个线程执行了,因为执行完的线程复用,继续执行其他任务。

ThreadName = myThread=1
ThreadName = myThread=3
ThreadName = myThread=4
ThreadName = myThread=5
ThreadName = myThread=2
ThreadName = myThread=6
ThreadName = myThread=3
ThreadName = myThread=8
ThreadName = myThread=1
ThreadName = myThread=2
ThreadName = myThread=10
ThreadName = myThread=7
ThreadName = myThread=2
ThreadName = myThread=11
ThreadName = myThread=4
ThreadName = myThread=5
ThreadName = myThread=8
ThreadName = myThread=6
ThreadName = myThread=3
ThreadName = myThread=9
ThreadName = myThread=12

newSingleThreadExecutor:多个任务排队进行,线程数为 1,依次执行。

ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1
ThreadName = myThread=1