线程池中的拒绝策略是什么东东?

一、拒绝策略产生缘由?

线程池工作中,如果任务量很大,超过系统实际承载能力时,如果不予理睬,接着可能系统就崩溃了,所以jdk内置提供了线程池的4种拒绝策略,合理的解决这种问题。

二、何时触发使用拒绝策略

线程池中线程已经用完不能再创建了,等待队列也排满了,此时如果再来新任务,就会执行下面的拒绝策略之一。

主要配合线程池使用

三、拒绝策略都有哪些?

1、AbortPolicy策略

使用该策略会直接抛异常,阻止系统正常工作。

2、CallerRunsPolicy策略

只要线程池没有关闭,该策略直接在调用者线程中,运行当前被丢弃的任务,虽然不会真的丢弃任务,但是任务提交线程的性能极有可能急剧下降。

3、DiscardOldestPolicy策略

该策略将丢弃即将执行的下一个任务,并尝试再次提交当前任务。

4、DiscardPolicy策略

该策略默默丢弃没法处理的任务,不予处理。如果允许任务丢失,这可能是最好的一种解决方案了。

5、自定义拒绝策略

1)、先来看下 jdk内置拒绝策略的定义。
在这里插入图片描述
DiscardOldestPolicy 的源码实现:
在这里插入图片描述
作为子类,他们都实现了 RejectedExecutionHandler 接口 ,通过重写接口方法(参数 r 为任务线程,参数 e 为当前的线程池 ),以父类作为参数传入自定义的线程池 (如果觉得描述不清楚,可参看下面线程池通过接口回调的方式使用拒绝策略的小demo)。
在这里插入图片描述
不知道小伙伴们看着眼熟不,乍一看,呦呵,这个自定义线程池还默默的用了一下设计模式呢~
拒绝策略以接口形式作为参数,实际调用的时候传入的是该接口的子类,而线程池使用的是其重写的拒绝策略方法。soga~原来是使用了策略模式啊。但是如果您看这个线程池的核心工作代码,又能知道了,他还用了模板模式,所以准确来讲,他使用了典型的组合:模板模式+策略模式

2)、哦哦,原来酱紫啊,如果jdk内置拒绝策略无法满足你的需求,那你也可以自定义拒绝策略咯~
就是照着葫芦画片,也实现这个接口,并重写他的方法呀。调用的话,就按照上面的截图形式,把子类传进去,或者接口回调的形式也可以。

到此,拒绝策略介绍完毕。

如果觉得上面阐述的不够清楚,可以看下面的demo

四、线程池使用拒绝策略demo

public class RejectThreadPoolDemo {
    public static void main(String[] args) throws InterruptedException {
        MyTask task=new MyTask();
      ExecutorService es=  new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(10), Executors.defaultThreadFactory(), new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println(r.toString()+" is discard");
            }
        });

      for (int i=0;i<Integer.MAX_VALUE;i++){
          es.submit(task);
          Thread.sleep(10);
      }
    }
    public static class MyTask implements Runnable{
        @Override
        public void run(){
            System.out.println(System.currentTimeMillis()+": Thread ID :"+Thread.currentThread().getId());

            try {
                Thread.sleep(100);
            }catch (InterruptedException e){
                System.out.println(e);
            }
        }
    }
}

结果;
在这里插入图片描述
该线程池核心线程数和最大线程数都是5,等待队列容量为10个,自定义拒绝策略,不抛出异常,避免任务提交端没做异常处理导致出现其他的状况。选择只打印丢弃任务的信息,比内置的DiscardPolicy策略高级一点点。

在实际应用中,可以将日志信息记录的更详细一点,来分析系统的负载和任务丢失的情况。

这种固定大小的线程池,最好不要设置无界队列,如果任务量很大,消费又很慢,那队列会一直扩容,很可能把内存撑爆。

参考书籍《java高并发程序设计》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值