本章主要介绍了为什么要使用线程池、如何使用线程池以及内部原理。
Java中的线程池是运用场景最多的并发框架,合理地使用线程池能够带来3个好处:
- 降低资源消耗
- 提高响应速度
- 提高线程的可管理性
线程池的实现原理
处理流程:
ThreadPoolExecutor执行示意图:
线程池的使用
线程池的创建
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime,milliseconds,runnableTaskQueue, handler);
几个重要参数:
- corePoolSize(线程池的基本大小)
- runnableTaskQueue(任务队列)
- ArrayBlockingQueue
- LinkedBlockingQueue
- SynchronousQueue
- PriorityBlockingQueue
- maximumPoolSize(线程池最大数量)
- ThreadFactory:用于设置创建线程的工厂
- RejectedExecutionHandler(饱和策略)
向线程池提交任务
可以使用两个方法向线程池提交任务,分别为execute()和submit()方法。
1 | threadsPool.execute(new Runnable() { |
1 | Future<Object> future = executor.submit(harReturnValuetask); |
关闭线程池
可以通过调用线程池的shutdown或shutdownNow方法来关闭线程池。
合理地配置线程池
要想合理地配置线程池,可以从以下几个角度来分析(建议使用有界队列):
- 任务的性质:CPU密集型任务、IO密集型任务和混合型任务。
- 任务的优先级:高、中和低。
- 任务的执行时间:长、中和短。
- 任务的依赖性:是否依赖其他系统资源,如数据库连接。
线程池的监控
通过线程池提供的参数进行监控,在监控线程池的时候可以使用以下属性。通过扩展线程池进行监控。可以通过继承线程池来自定义线程池,重写线程池的beforeExecute、afterExecute
和terminated方法,也可以在任务执行前、执行后和线程池关闭前执行一些代码来进行监控。
- taskCount:线程池需要执行的任务数量。
- completedTaskCount:线程池在运行过程中已完成的任务数量,小于或等于taskCount。
- largestPoolSize:线程池里曾经创建过的最大线程数量。
- getPoolSize:线程池的线程数量。
- getActiveCount:获取活动的线程数。