0


线程池的拒绝策略

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


前言

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

一、线程池是什么?


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

二、测试展示:

     为了提高线程的可靠性,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 策略。
标签: java 开发语言

本文转载自: https://blog.csdn.net/m0_65004039/article/details/126443886
版权归原作者 来日方长。。。。long 所有, 如有侵权,请联系我们删除。

“线程池的拒绝策略”的评论:

还没有评论