线程池的拒绝策略

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

 


前言

        面对自动创建线程会面临的诸多像线程创建启动过多,核心线程数量使用完后对于后续线程的加入,线程池提供了四种拒绝策略,为了便于后续学习,我对其做了一些简单的总结。

一、线程池是什么?


        线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。而线程拒绝策略则是线程管理线程,防止线程运行过多而采取的一种管理策略。

二、测试展示:

         为了提高线程的可靠性,Java标准类库引入了一个RejectedExecutionHandler接口,用于封装被拒绝任务的处理策略。可以通过线程池的构造器参数handler,或者setRejectedExecutionHandler方法来为线程池关联一个RejectedExecutionHandler。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler);

        handler:线程池饱和时,封装被拒绝任务的处理策略
        抽象方法:abstract void rejectedExecution(Runnable r,ThreadPoolExecutor executor);
        r代表被拒绝的任务,executor代表拒绝任务r的线程池实例。
 


1.关于RejectedExecutionHandler操作说明



    1. 当客户端提交的任务被拒绝时,线程池所关联的RejectedExecutionHandler的
      rejectedExecution方法会被线程池调用。
    2.ThreadPoolExecutor自身提供了几个现成的RejectedExecutionHandler
        接口的实现类。其中ThreadPoolExecutor.AbortPolicy是
      ThreadPoolExecutor使用的默认RejectedExecutionHandler。
    3. 如果默认的RejectedExecutionHandler(它会直接抛出异常)无法满足要求,
        那么我们可以优先考虑ThreadPoolExecutor自身提供的其他
      RejectedExecutionHandler,其次才去考虑使用自身实现的
      RejectedExecutionHandler接口。
   


2.其他实现类的表现:



        实现类                                                          所实现的处理策略
        ThreadPoolExecutor.AbortPolicy                   直接抛出异常
        ThreadPoolExecutor.DiscardPolicy               丢弃当前被拒绝的任务(而不抛出任何异常)
        ThreadPoolExecutor.DiscardOldestPolicy     将工作队列中最老的任务丢弃,然后重新                                                                                  尝试接纳被拒绝的任务
        ThreadPoolExecutor.CallerRunsPolicy           在客户端线程中执行被拒绝的任务
*/

        1.AbortPoilcy( 直接抛出异常):

        测试代码

public static void main(String[] args) throws Exception{
	        int corePoolSize = 5;
	        int maximumPoolSize = 10;
	        long keepAliveTime = 5;
            //创建阻塞队列队列为10
	        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(10);
            //调用AbortPoilcy
	        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
              //创建线程池
	        ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue, handler);
	        Runnable r = () -> System.out.println(Thread.currentThread().getName() + " is running");
	        for(int i=0; i<100; i++) {
	            try {
	                executor.execute(r);
	            } catch (Exception e) {
	                e.printStackTrace();
	            }
	        }
            //关闭线程池
	        executor.shutdown();
	    }

        运行结果展示

        使用execute()提交任务,会抛出运行期异常,java.util.concurrent.RejectedExecutionException:如果没有执行异常抛出的话,不会执行一百次线程,可自行测试下,很容易在控制台console中能查看到。


2.DiscardPolicy(丢弃当前被拒绝的任务(而不抛出任何异常)

        当任务添加到线程池中被拒绝时,默认情况下它将丢弃被拒绝的任务。(即该策略下,直接丢弃任务,什么都不做)

//同上,只给出要修改的部分,其他测试主题不变
RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();

        运行结果展示:

可以看到旁边是没有滚动条,所以,显而易见的,他并没有一百条线程执行结果,有一部分被直接进行丢弃,也没有抛出异常,


 3、DiscardOldestPolicy()

                DiscardOldestPolicy策略的作用是,当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。

RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy();

        运行结果展示

 从上面运行结果控制台上的滚动条展示效果,也没有达到一百条运行结果,所以,这种拒绝策略也进行了线程的拒绝,


 

4、CallerRunsPolicy(在客户端线程中执行被拒绝的任务)


//,只需要将拒绝策略代码改为,主体代码不变。查看运行结果
RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

     运行结果如下:

        运行后,在控制台console中能够看到的是,会有一部分的数据打印,显示的是 “main is running”,


总结        

        线程池的构造函数中所表现的,拒绝策略是一种管理线程运行的策略,对当前线程的调度,对后续线程的接受和使用,现场城池的高效,有很大一部分是由线程池的拒绝策略实现的,四种拒绝策略是相互独立无关的,选择何种策略去执行,还得结合具体的场景。实际工作中,一般直接使用 ExecutorService 的时候,都是使用的默认的 defaultHandler ,也即 AbortPolicy 策略。

  • 19
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值