- 线程池的工作原理:
- 当任务过来时,如果线程池中的线程数小于核心线程数,就创建线程。(默认情况下,线程池不会预先创建线程,但可以配置)
- 当核心线程数满了以后,提交过来的任务会放到阻塞队列里。
- 如果核心线程数满了,阻塞队列也放满了,就会继续创建新的线程,直至线程池的线程数量达到最大线程数。
- 如果线程池中的线程数量已经达到了最大线程数,此时仍有任务提交过来,那么久要执行拒绝策略。
- 如果线程的空闲时间超过了设定的空闲存活时间,并且线程池中的线程数量大于核心线程数时,就要销毁线程,直到等于核心线程数。(allowCoreThreadTimeOut设为true,也可以继续销毁空闲的核心线程)
- 线程池的相关参数设定:
- 核心线程数 (线程池在运行过程中也可以修改)
- 最大线程数
- 空闲存活时间
- 阻塞队列
- 线程工厂
- 拒绝策略
- 以下参数在运行过程中,可以动态修改。(除了阻塞队列不可以修改)
- 线程池生命周期
- RUNNING 线程池可以接受新的任务并处理已提交的任务。
- SHUTDOWN:通过shutdown()进入,该状态下线程池不再接收新的任务,但是会继续处理已提交的任务。
- STOP:通过shutdownNow()进入,该状态下线程池会试图中断所有正在执行的任务,并清空阻塞队列。
- 线程中断用的是Thread.interrupt()实现的,它的中断取决于在任务中是否实现具体的中断相应方式。如(interrupted),否则也无法强制中断。
- shutdownNow() 会返回阻塞队列中所有未执行的任务。
- TERMINATED:terminated()方法执行完毕后进入该状态,所有的任务处理完毕且线程池完全关闭后。
- 线程池种类
- newCachedThreadPool : 不限制线程数量,只要有新任务就会创建是线程,所以这里它用的是SynchronousQueue,空闲60秒线程就会回收。适合短期大量的并发任务。
- newFixedThreadPool:线程数固定,线程会进行复用,线程都在忙,任务就会放进阻塞队列中。
- newScheduledThreadPool:可以定时或固定周期的执行任务,线程池大小也可以指定。这里用到了DelayedWorkQueue。
- newSingleThreadExecutor:只有一个线程,保证任务执行的顺序。
- 拒绝策略
- AbortPolicy 抛出异常
- DiscardPolicy丢弃任务不抛异常
- DiscardOldestPolicy丢弃最早的任务
- CallerRunsPolicy由调用者线程执行任务,以达到减缓任务提交的效果
- 实现RejectedExecutionHandler,进行自定义拒绝策略