阅读 1631

线程池的拒绝策略以及拒绝策略的重写

简介:

在Jdk1.5 版本时新增了JUC并发编程包,极大的简化了传统的多线程开发,作为一名java开发者,了解在并发场景下使用线程池对线程进行管理是非常有必要的;

概念:

Java线程池,是典型的池化思想的产物,类似的还有数据库的连接池、redis的连接池等。池化思想,就是在初始的时候去申请资源,创建一批可使用的连接,在处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务来执行;

线程池拒绝的达成条件:

在JAVA的线程池中,有3个很重要的参数,这些参数决定了拒绝策略的是否使用:

1.corePoolSize - 核心线程数,也即最小的线程数。

2.workQueue - 具体阻塞队列 。 

3.maximumPoolSize - 最大线程数

  当提交任务数大于 corePoolSize 的时候,会优先将任务放到 workQueue 阻塞队列中。当阻塞队列饱和后,会扩充线程池中线程数,直到达到 maximumPoolSize 最大线程数配置。此时,再多余的任务,则会触发线程池的拒绝策略了。

线程池的具体类型与定义:

 拒绝策略提供顶级接口 RejectedExecutionHandler ,其中方法 rejectedExecution 即定制具体的拒绝策略的执行逻辑。

Jdk默认提供了四种拒绝策略:

1.CallerRunsPolicy - 当触发拒绝策略,只要线程池没有关闭的话,则使用调用线程直接运行任务。一般并发比较小,性能要求不高,不允许失败。但是,由于调用者自己运行任务,如果任务提交速度过快,可能导致程序阻塞,性能效率上必然的损失较大

2.AbortPolicy - 丢弃任务,并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。我们在调用线程处必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行。

3.DiscardPolicy - 直接丢弃,不执行其他操作

4.DiscardOldestPolicy - 当触发拒绝策略,只要线程池没有关闭的话,丢弃阻塞队列workQueue 中最老的一个任务,并将新任务加入

拒绝策略的重写:

在实际开发中,可能线程池通用的这四种拒绝策略无法满足我们的业务场景需要,这个时候需要对拒绝策略进行重写处理;

For Example:

1.拒绝策略的接口实现 

public interface RejectedExecutionHandler {  
void rejectedExecution(Runnable r, 
    ThreadPoolExecutor executor);
 }复制代码

2.重写示例:

我们只需要将我们对线程池的自定义拒绝策略在线程池创建时传入即可改变原有拒绝策略;

实现Demo如下:

package com.hinson.study;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class RejectedDemo implements RejectedExecutionHandler{
	public RejectedDemo(){	}
	
	@Override
	public void rejectedExecution(Runnable runnable , ThreadPoolExecutor executor) {		System.out.println("线程池自定义处理..");
		System.out.println("当前被拒绝任务为:" + runnable.toString());		
	}
}
复制代码


文章分类
后端
文章标签