聊聊线程池

线程池:指管理一组同构工作线程的资源池。线程池与工作队列(Work Queue)密切相关,其中在工作队列中保存了所有等待执行的任务。工作线程(Worker Thread)的任务很简单:从工作队列中获取一个任务,执行任务,然后返回线程池并等待下一个任务。

线程池的优势:通过重用现有线程而不是创建新线程,可以处理多个请求时分摊在线程创建和销毁过程中产生的巨大开销,另外任务到达,工作线程通常存在,提高了响应性。


通过Executors中静态工厂方法来创建一个线程池:

newFixedThreadPool,将创建一个固定长度的线程池,每提交一个任务就创建一个线程,直到达到线程池的最大数量。如果发生未预期的异常,线程池还会补充一个新线程。

newCachedThreadPool,将创建一个可缓存的线程池,如果线程池的当前规模超过处理需求,那么将回收空闲线程,当需求增加,可添加新线程。

newSingleThreadExecutor,是一个单线程的Executor,它将创建单个工作线程来执行任务,如果这个线程异常结束,会创建另外一个替代,该线程可确保依照任务队列中的顺序串行执行

newScheduledThreadPool,创建一个固定长度的线程池,而且以延迟或定时的方式来执行任务。

ExecutorService的生命周期有3种状态:运行、关闭和已终止。shutdow方法将执行平缓的关闭过程,即不再接受新的任务,同时等待已经提交的任务完成。shutdowNowd方法将执行粗暴的关闭过程,尝试取消所有运行中的任务,并且不再启动队列中尚未开始执行的任务。ExecutorService关闭后提交的任务将由“拒绝执行处理器”来处理,抛弃任务或使得execute方法抛出一个未检出的RejectedExecutionException,最后ExecutorServie进入终止状态。

携带结果的任务Callable与Future

饱和策略:当有界队列被填满后,饱和策略开始发挥作用。ThreadPoolExecutor的饱和策略可以通过调用setRejectedExecutionHandler来修改。

AbortPolicy:终止,是默认的饱和策略,该策略会抛出RejectedExecutionException。

DiscardPolicy:当新提交的任务无法保存到队列中,该策略会抛弃该任务。

DiscardOldestPolicy:会抛弃下一个将被执行的任务,然后尝试提交新任务(优先级队列与该策略最好不同时使用)。

CallerRunsPolicy:该策略不会抛弃任务,也不会抛出异常,而是将某些任务回退给调用者,从而降低新任务的流量。

以WebService为例,使用有界队列和CallerRunPolicy时,当线程池所有线程都被占用,工作队列被填满,下一个任务会在调用execute的主线程中执行。这期间,主线程不会调用accept,因此请求将被保存到TCP层的队列,如果持续过载,TCP层请求队列被填满,开始抛弃请求,导致服务期在高负载下实现一种平缓的性能降低。

参考:

《Java并发编程实战》

你可能感兴趣的:(聊聊线程池)