线程池工作原理
线程池的优点:
Java的线程池是当前应用最普遍的一种并发框架。在并发编程中,合理的使用线程池能够带来一系列的好处。
1、降低资源消耗。线程池通过重复利用已创建的线程,从而降低线程创建和销毁的开销;
2、提高响应速度。当任务到达时,任务可以不用等待创建线程,利用现成的线程资源就能立即执行。
3、提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。
线程池中类关系
Executor是一个接口,它是Executor框架的基础,它将任务的提交与任务的执行分离开来。
ExecutorService接口继承了Executor,在其上做了一些shutdown()、submit()的扩展,是真正的线程池接口。
AbstractExecutorService抽象类实现了ExecutorService接口中的大部分方法。
ThreadPoolExecutor是线程池的核心实现类,用来执行被提交的任务。
ScheduledExecutorService接口继承了ExecutorService接口,提供了带"周期执行"的功能。
ScheduledThreadPoolExecutor是一个实现类,可以在给定的延迟后运行命令,或者定期执行命令。
创建线程池:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
// ...
}
corePoolSize:线程池中的核心线程数,当提交一个任务时,线程池创建一个新线程执行任务,直到当前线程数等于corePoolSize。如果当前线程数为corePoolSize,继续提交的任务被保存到阻塞队列中,等待被执行。如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程。
maximumPoolSize:线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize。
keepAliveTime:线程空闲时的存活时间,即当线程没有任务执行时,继续存活的时间。默认情况下,该参数只对非核心线程起作用,即在线程数大于corePoolSize时才有用。核心线程创建了会一直存活。可以通过allowCoreThreadTimeOut()方法设置对核心线程也起作用。
TimeUnit:keepAliveTime的时间单位,有ns、ms、s、m、h等。
workQueue:是阻塞队列(BlockingQueue)。当线程池中的线程数超过它的corePoolSize的时候,线程会进入阻塞队列进行阻塞等待。通过workQueue,线程池实现了阻塞功能。
threadFactory:线程创建工厂,通过自定义的工厂可以给每个新建的线程设置一个具有识别度的线程名,当然还可以更加自由的对线程做更多的设置,比如设置所有的线程为守护线程等。线程池默认的threadFactory,将线程按照“pool-数字-thread-数字”规则命名。
RejectedExecutionHandler:线程池拒绝策略。当阻塞队列满了,且没有空闲的工作线程,此时继续提交任务,则执行拒绝策略。用户可以自定义拒绝策略,进行记录日志或者对任务进行持久化等。线程池本身提供了4种策略:
AbortPolicy:直接抛出异常,默认策略;
CallerRunsPolicy:用调用者所在的线程来执行任务;
DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
DiscardPolicy:直接丢弃任务;
线程池工作机制
上文介绍线程池各参数的时候,已经提到了线程池的工作流程。这里单独提出来总结。当用户用户提交任务。
1、当前运行任务的线程少于corePoolSize,则创建新线程来执行任务;
2、当前运行任务的线程数大于等于corePoolSize,则将任务加入BlockingQueue;
3、阻塞队列已满,新的任务无法加入,则再创建新的线程来处理;
4、运行任务的线程数超过maximumPoolSize,则调用RejectedExecutionHandler.rejectedExecution() 方法,执行拒绝策略。
- 本文标签: 多线程 线程池
- 本文链接: http://www.ityoulove.com/article/38
- 版权声明: 本文由崔健宇原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权