Java基础教程:多线程基础——线程池

Java基础教程:多线程基础——线程池

线程池

  《阿里巴巴Java开发手册》有如下一则:

  Java基础教程:多线程基础——线程池

  说明里介绍的很清楚,总结来说是这样的:

  • 线程的创建和销毁是耗时较长、耗系统资源较多的操作
  • 将线程放到线程池中,方便管理,且提高线程的复用性,即一个线程可以分配给多个任务使用。

  

线程池原理

线程池状态及数量

  线程池运行的状态,并不是用户显式设置的,而是伴随着线程池的运行,由内部来维护。线程池内部使用一个变量维护两个值:运行状态(runState)和线程数量 (workerCount)。在具体实现中,线程池将运行状态(runState)、线程数量 (workerCount)两个关键参数的维护放在了一起,如下代码所示:

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); //运行状态 & 线程数量
private static final int COUNT_BITS = Integer.SIZE - 3; private static final int RUNNING = -1 << COUNT_BITS;
...
private static int ctlOf(int rs, int wc) { return rs | wc; }

  线程状态分为五种:  

  Java基础教程:多线程基础——线程池

  线程池的生命周期:

  Java基础教程:多线程基础——线程池

任务执行机制

  所有任务的调度都是由execute方法完成的,这部分完成的工作是:检查现在线程池的运行状态、运行线程数、运行策略,决定接下来执行的流程,是直接申请线程执行,或是缓冲到队列中执行,亦或是直接拒绝该任务。其执行过程如下:

  1. 如果正在运行的线程少于corePoolSize线程,请尝试使用给定任务作为其第一个任务来启动新线程。 对addWorker的调用原子地检查runState和workerCount,从而通过返回false来防止在不应该添加线程的情况下发出错误警报。
  2. 如果任务可以成功排队,那么我们仍然需要仔细检查是否应该添加线程(因为现有线程自上次检查后就已死亡)或自进入此方法以来该池已关闭。 因此,我们重新检查状态,并在必要时回滚排队,如果已停止,或者在没有线程的情况下启动新线程。
  3. 如果我们无法将任务排队,则尝试添加一个新线程。 如果失败,则表明我们已关闭或已饱和,因此拒绝该任务。

任务缓存

  线程池的本质是对任务和线程的管理,阻塞队列负责缓存任务,工作线程从队列中获取任务以便执行

说明:阻塞队列(BlockingQueue),即在普通队列的基础上实现以下两个附加操作

  • 当队列满时,队列会阻塞插入元素的线程,直到队列不满。
  • 当队列空时,队列会阻塞获取元素的线程,知道队列不空。

  

参考资料

上一篇:Java基础教程:多线程基础(2)——线程间的通信


下一篇:Java基础教程:多线程基础(4)——Lock的使用