线程池学习笔记

Posted by me2in Blog on October 14, 2020

1. 了解线程池

1.1 WHAT:线程池是什么?

JDK1.8中的Javadoc中是这么说的:

An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.

提供一组方法可以对一个或者多个异步任务终止执行或者提供Future方法用于追踪执行进度

解决了两个不同的问题:

  1. 减少了每个任务的调用开销,通常在执行大量异步任务时可提供改进的性能。
  2. 绑定和管理执行一组集合任务时所消耗的资源(包括线程)。每个ThreadPoolExecutor还维护一些基本统计信息,例如已完成任务的数量。

总结一下,线程池内部维护了一个或者多个的worker,通过外部方法可提交任务到线程池中,开发者无需再自行管理线程的生命周期,使用线程池技术即可实现动态扩容。

1.2 HOW:怎么用线程池

JDK提供了三种线程池的实现:ThreadPoolExecutor,ForkJoinPool,ScheduledThreadPoolExecutor。分别介绍下三者的使用场景

  1. ThreadPoolExecutor 也是ScheduledThreadPoolExecutor的父类。这是我们最常使用的实现,通常会使用Executors的工厂方法来获得新实例。重点介绍下该类的构造函数

     public ThreadPoolExecutor(int corePoolSize,//核心线程数,核心线程通常不会被超时回收,除非设置allowsCoreThreadTimeOut为true
                                  int maximumPoolSize,//最大线程数,是指线程池中最多存在的线程个数
                                  long keepAliveTime,//线程最大空闲时间,超时的线程会被回收,通常不会回收核心线程
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> workQueue,//工作队列,这里指定不同类型的队列使线程池呈现不同的执行结果
                                  ThreadFactory threadFactory,//线程工厂对象,可以初始化线程的名称,group等
                                  RejectedExecutionHandler handler) {//线程最多可以容许maximumPoolSize+workQueue.size()个任务,超出的会执行拒绝策略,内置的有4种:直接执行、中断异常、忽略、剔除旧任务
         ....
     }
    
  2. ScheduledThreadPoolExecutor 可以设置任务在给定的延迟后运行或定期执行。当需要多个工作线程,或者需要ThreadPoolExecutor(此类扩展)的附加灵活性或功能时,此类比Timer更好。由于是ThreadPoolExecutor的子类,所以该类的构造方法内部其实是调用了父类的构造方法,需要注意的是队列类型使用的是DelayedWorkQueue类型,

    public ScheduledThreadPoolExecutor(int corePoolSize,//核心线程同上
                                           ThreadFactory threadFactory,//线程工厂对象,可以初始化线程的名称,group等
                                           RejectedExecutionHandler handler) {//
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
                  new DelayedWorkQueue(), threadFactory, handler);
        }
    
  3. ForkJoinPool 此类比较特殊,当你需要把一个大任务分解为多个小任务并行执行时,并将多个结果汇总,可以使用这个线程池。类似于MapReduce分而治之的思路,内部使用work-stealing工作机制,不同线程默认执行自己的任务,在空闲下来时也可执行别的线程的任务,Stream中的ParallelStreams方法也用到了该类。

2.任务是如何被提交的

3. 任务在何时被处理

4.如果任务过多或者没有新的任务进来会怎样