关于java:Java-线程池四种拒绝策略

jdk1.5版本新增了 JUC 并发包,其中一个蕴含线程池。

四种回绝策略:

回绝策略类型 阐明
1 ThreadPoolExecutor.AbortPolicy 默认回绝策略,回绝工作并抛出工作
2 ThreadPoolExecutor.CallerRunsPolicy 应用调用线程间接运行工作
3 ThreadPoolExecutor.DiscardPolicy 间接回绝工作,不抛出谬误
4 ThreadPoolExecutor.DiscardOldestPolicy 触发回绝策略,只有还有工作新增,始终会抛弃阻塞队列的最老的工作,并将新的工作退出

事后配置

配置线程池。

  • 外围线程和最大线程都尽量设置的小一点,别离设置成 1 和 2
  • 阻塞队列设置固定长度的有界队列,长度为 1
  • 线程工厂设置默认线程工厂
// 外围线程数
int corePoolSize = 1;
// 最大线程数
int maximumPoolSize = 2;
// 线程存活工夫
long keepAliveTime = 10;
// 线程存活工夫单位
TimeUnit unit = TimeUnit.SECONDS;
// 有界队列 遵循 FIFO 准则
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(1);
// 线程工厂
ThreadFactory threadFactory = Executors.defaultThreadFactory();

创立线程工作

创立线程工作,一个线程工作执行一秒:

class TaskThread implements Runnable{
                
        private int i;

        public TaskThread(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(2);
                System.out.println("执行工作:" + i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

回绝策略一:AbortPolicy

默认回绝策略,回绝工作并抛出工作

// 回绝策略 默认回绝策略,回绝工作并抛出异样:
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                unit,
                workQueue,
                threadFactory,
                handler);
        for (int i = 1; i <= 5; i++) {
            try {
                threadPool.execute(new TaskThread(i));
            } catch (Exception e) {
                System.out.println("【工作" + i + "】报错:" + e.getMessage());
            }

        }

输入

【工作】4报错:Task com.test.controller.ThreadPoolController$TaskThread@5c0369c4 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0]
【工作】5报错:Task com.test.controller.ThreadPoolController$TaskThread@31b7dea0 rejected from java.util.concurrent.ThreadPoolExecutor@50675690[Running, pool size = 2, active threads = 2, queued tasks = 1, completed tasks = 0]
执行工作:1
执行工作:3
执行工作:2

最大线程数 + 阻塞队列 = 3,执行到4,5的时候就抛出谬误。这里须要用 try catch 捕捉异样。工作1、2、3失常执行。

如果提交的工作都要执行,能够将抛出的谬误工作存入在redis中,而后定时从redis中获取工作,再提交执行。

回绝策略二:CallerRunsPolicy

调用线程运行多余的工作。

更换回绝策略,将下面的 AbortPolicy 换成 CallerRunsPolicy

RejectedExecutionHandler handler = new ThreadPoolExecutor.CallerRunsPolicy();

执行工作,输入:

执行工作:1
执行工作:4
执行工作:3
执行工作:2
执行工作:5

最大线程数 + 阻塞队列 = 3,多余的工作还是持续被执行。

回绝策略三:DiscardPolicy

回绝工作,不会抛出谬误。
更换策略,将CallerRunsPolicy 换成DiscardPolicy:

RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardPolicy();

执行工作,输入:

执行工作:1
执行工作:3
执行工作:2

多余的线程工作提交被回绝,而只执行最大线程数 + 阻塞队列 数量的工作,并且不会抛出谬误。

回绝策略四:DiscardOldestPolicy

只有还有工作新增,始终会抛弃阻塞队列的最老的工作,并将新的工作退出到阻塞队列中
更换策略,将DiscardPolicy 换成DiscardOldestPolicy:

RejectedExecutionHandler handler3 = new ThreadPoolExecutor.DiscardOldestPolicy();

执行工作,输入:

执行工作:3
执行工作:1
执行工作:5

工作的执行程序是 外围线程数 —> 阻塞队列 —> 最大线程数,其中工作1,工作3提交胜利。

  • 工作2因为在阻塞队列中,
  • 前面的工作4把工作2挤掉,
  • 工作5又把工作4挤掉,所以最初执行的是工作5。

总结

本文介绍了线程四种回绝策略,当工作工作大于最大线程 + 阻塞队列会执行阻塞队列。

  • AbortPolicy 默认策略,回绝工作,并抛出异样
  • CallerRunsPolicy 调用线程执行对于的工作
  • DiscardPolicy 回绝工作,不会抛出异样
  • DiscardOldestPolicy 有多余的工作,把阻塞队列最老的工作抛弃,放入新的工作,直到没有新的工作。
    如果感觉文章对你有帮忙的话,请点个赞吧!

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理