一、线程池的优点和处理流程
1、优点
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。
2、处理流程
二、扩展知识
1、corePoolSize和maximumPoolSize可以在创建之后使用setCorePoolSize()、setMaximumPoolSize()进行改变。
2、核心线程默认是第一个任务到达时创建的,但是可以通过prestartCoreThread()、prestartAllCoreThreads()覆盖进行提前创建(传入一个非空队列时可使用)。
3、默认的ThreadFactory使用相同的ThreadGroup、相同的NORM_PRIORITY和non-daemon status创建线程,你可以使用自定义线程工厂修改线程名称、组、优先级、守护状态。创建线程失败newThread()返回null时,执行器继续工作,但是可能不会执行任务。
4、超出corePoolSize的额外线程(即非核心线程)如果它们空闲时间超过了keepAliveTime之后会被终止。可以通过allowCoreThreadTimeOut(boolean)让核心线程也会被超时回收。
5、队列的策略通常三种
直接传递:SynchronousQueue(通常要求maximumPoolSizes*避免新任务被拒绝)。
*:LinkedBlockingQueue(maximumPoolSize没有效果,不会创建非核心线程)。
有界:ArrayBlockingQueue(大队列少线程可以最小化CPU使用率、OS资源和上下文切换,但是会降低吞吐量。如果任务频繁阻塞,可以分配更多线程。小队列多线程可以保持CPU繁忙但是会带来更多的调度开销,也可能降低吞吐量)。
6、拒绝策略
AbortPolicy:默认的,抛出RejectedExecutionException。
CallerRunsPolicy:调用execute()的线程执行,可以提供简单反馈控制但是减缓任务提交速度。
DiscardPolicy:丢弃任务。
DiscardOldestPolicy:先丢掉队列首部任务,再execute,再次失败时将导致重复。
7、钩子方法
beforeExecute(Thread, Runnable)和afterExecute(Runnable, Throwable)会在每个任务execute之前和之后被调用,可以用来做一些监控或者日志记录等。钩子方法抛出异常可能导致线程失败或终止。
8、可以使用getQueue()获取任务队列然后remove/purge做一些任务回收管理。
9、程序不在引用并且没有存活线程的pool将会自动shutdown。
10、线程池运行状态(跟线程状态是两个概念哈)
RUNNING: Accept new tasks and process queued tasks
SHUTDOWN: Don't accept new tasks, but process queued tasks
STOP: Don't accept new tasks, don't process queued tasks, and interrupt in-progress tasks
TIDYING: All tasks have terminated, workerCount is zero, the thread transitioning to state TIDYING will run the terminated() hook method
TERMINATED: terminated() has completed
11、线程池运行状态转换图(跟线程状态转换图是两个概念哈)