您的位置:首页 > 编程语言 > Java开发

java并发编程的艺术第九章——java中的线程池

2017-08-26 00:00 316 查看

1、线程池的三个好处:

降低资源消耗。可以重复利用已创建的线程,降低创建/销毁线程的开销

提高响应速度。

提高线程的可管理性。统一分配、调优、监控。

2、线程池的处理流程

新任务提交至线程池后的处理流程:

1.核心线程池是否已满,如果没满,则创建一个线程执行任务,如果满了,则进入下一个流程

2.判断队列是否已经满了,如果没满,则将任务存储在队列中,如果满了,则进入下一个流程

3.判断线程池是否已经满了,如果没满,则创建线程执行任务,如果满了,则按照策略处理无法执行的任务。

3、线程池的使用

3.1、线程池的创建
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)


corePoolSize:线程池的基本大小

maximumPoolSize:线程池的最大线程数

keepAliveTime:线程的活动的保持时间。当线程空闲之后,保持存活的时间,如果任务量大,而任务的执行时间又短的话,可以增大线程池的存活时间,提高线程的利用率

TimeUnit:线程活动保持时间的单位

BlockingQueue:用于存放任务的阻塞队列,队列的选择可以参考java中的阻塞队列

ThreadFactory:用于设置创建线程的工厂。

RejectedExecutionHandler:饱和策略。即当线程和队列都已经满了的时候,应该采取什么样的策略来处理新提交的任务,默认策略是AbortPolicy(抛出异常),其他的策略还有:CallerRunsPolicy(只用调用者所在线程来运行任务),DiscardOldestPolicy(丢弃队列里最近的一个任务,并执行当前任务),DiscardPolicy(不处理,丢弃掉)

3.2、向线程池提交任务
提交任务有两种方法,分别是execute()和submit()。

execute()方法适用于任务提交之后没有返回值的这种情况,因为没有返回值,所以提交任务之后我们也无法判断任务是否执行成功。

submit方法适用于提交任务之后有返回值的情况,它会返回一个Future类型的对象,可以通过future.get()方法来获取返回值,get()会阻塞线程直到任务完成。

3.3、关闭线程池
关闭线程池有两种方法,分别是shutdown()和shutdownNow(),它们的原理都是遍历线程池中所有的线程,分别调用每个线程池的interrupt()方法来中断线程。但是它们存在一定的区别,shutdownNow首先将线程池的状态设置成STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表,而shutdown只是将线程池的状态设置成SHUTDOWN状态,然后中断所有没有正在执行任务的线程。

3.4、合理的配置线程池
线程池配置的分析角度

任务的性质:IO密集型还是CPU密集型,cup密集型可以配置小一点的线程数,io密集型可以配置多的线程数

任务的优先级:可以用PriorityBlockingQueue队列来处理

任务处理时间的长短

任务的依赖性:比如说是否依赖数据库连接

线程池的任务队列的选择建议使用有界队列,因为如果任务太多,有界队列可以抛出异常便于我们排查,而无界队列会使队列中的任务越来越多,可能导致撑满内存,导致整个系统的不可用。

3.5、线程池的监控

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java线程池