【JUC源码】线程池:ThreadPoolExecutor(五)提炼总结

线程池系列:

经过前几篇对 ThreadPoolExecutor 的源码分析后,我们再对 ThreadPoolExecutor 的关键信息做一些总结:

1)线程池解决两个问题:

  • 通过减少任务间的调度开销 (主要是通过线程池中的线程被重复使用的方式),来提高大量任务时的执行性能
  • 提供了一种方式来管理线程和消费,维护基本数据统计等工作,比如统计已完成的任务数;

2)线程池容量相关参数:

  • coreSize:当新任务提交时,发现运行的线程数小于 coreSize,一个新的线程将被创建,即使这时候其它工作线程是空闲的,可以通过 getCorePoolSize 方法获得 coreSize

  • maxSize: 当任务提交时,coreSize < 运行线程数 <= maxSize,但队列没有满时,任务提交到队列中,如果队列满了,在 maxSize 允许的范围内新建线程;

    一般来说,coreSize 和 maxSize 在线程池初始化时就已经设定了,但我们也可以通过 setCorePoolSize、setMaximumPoolSize 方法动态的修改这两个值;

3)Keep-alive times 参数:

  • 作用: 如果当前线程池中有超过 coreSize 的线程,并且线程空闲的时间超过 keepAliveTime,当前线程就会被回收,这样可以避免线程没有被使用时的资源浪费;
  • 通过 setKeepAliveTime 方法可以动态的设置 keepAliveTime 的值;
  • 如果设置 allowCoreThreadTimeOut 为 ture 的话,core thread 空闲时间超过 keepAliveTime 的话,也会被回收;

4)线程池新建时的队列选择有很多,比如:

  • ArrayBlockingQueue,有界队列,可以防止资源被耗尽;
  • LinkedBlockingQueue,无界队列,未消费的任务可以在队列中等待
  • SynchronousQueue,为了避免任务被拒绝,要求线程池的 maxSize 无界,缺点是当任务提交的速度超过消费的速度时,可能出现无限制的线程增长

5)拒绝策略:在 Executor 已经关闭或对最大线程和最大队列都使用饱和时,可以使用 RejectedExecutionHandler 类进行异常捕捉。有如下四种处理策略:

  • AbortPolicy(默认):抛出异常
  • CallerRunsPolicy:不使用线程池,主线程来执行
  • DiscardPolicy:直接丢弃任务
  • DiscardOldestPolicy:丢弃队列中最老任务

6)ExecutorService 使用线程池中的线程执行提交的任务,线程池我们可以使用 Executors 进行配置.Executors 为常用的场景设定了可直接初始化线程池的方法,比如:

  • Executors#newCachedThreadPool 无界的线程池,并且可以自动回收
  • Executors#newFixedThreadPool 固定大小线程池
  • Executors#newSingleThreadExecutor 单个线程的线程池;

7)另外,线程池提供了很多可供扩展的钩子函数,比如有:

  • 提供在每个任务执行之前 beforeExecute 和执行之后 afterExecute 的钩子方法,主要用于操作执行环境,比如初始化 ThreadLocals、收集统计数据、添加日志条目等
  • 如果在执行器执行完成之后想干一些事情,可以实现 terminated 方法,如果钩子方法执行时发生异常,工作线程可能会失败并立即终止。

猜你喜欢

转载自blog.csdn.net/weixin_43935927/article/details/113965332