博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程池拒绝策略
阅读量:3950 次
发布时间:2019-05-24

本文共 2717 字,大约阅读时间需要 9 分钟。

  上一篇文章中,讲了;这篇文章主要说一下当任务队列已满并且线程池中的线程数量达到maximumPoolSize数量之后,还有任务到来,线程池是如何拒绝执行任务的。

拒绝策略

  还是结合创建线程池的源码来看:

public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue
workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }

在上面源码中的defaultHander就代表线程数量大于最大线程数的时候,线程池需要执行的拒绝策略。这里是设置了一个默认的拒绝策略。

1.ThreadPoolExecutor.AbortPolicy

丢弃任务并抛出RejectedExecutionException的异常。这是线程池默认的拒绝策略,建议比较重要的业务使用此策略,能够通过异常反馈来知晓程序的运行状况。

2.ThreadPoolExecutor.DiscardPolicy

丢弃任务,但是不会抛出任何异常。适合无关痛痒的业务使用。

3.ThreadPoolExecutor.DiscardOldestPolicy

丢弃任务队列中最前面的任务(等待时间最长),然后重新提交被拒绝执行的任务。此种策略的使用需要从实际情况分析业务中是否能够丢弃旧的任务。

4.ThreadPoolExecutor.AbortPolicy

由调用线程,也就是提交该任务的线程来处理该任务。

  在上一篇文章中,我们使用ThreadPoolExecutor来创建线程池的时候,并未指定拒绝策略,根据源码可以知道,线程池中设置一个默认的拒绝策略;

/**     * The default rejected execution handler     */    private static final RejectedExecutionHandler defaultHandler =        new AbortPolicy();

下面我们通过一个代码案例来验证一下:

public class test03 {
public static void main(String[] args) {
//创建线程数为2的一个线程池 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 500, TimeUnit.MILLISECONDS, new ArrayBlockingQueue
(5)); //提交需要执行的任务 for (int i = 0; i < 20; i++) {
threadPoolExecutor.execute(new RunnableImpl()); } //关闭线程池(注意:关闭线程池之后,线程也就不存在了,如果在关闭线程池之后又提交了需要执行的任务将会报错) threadPoolExecutor.shutdown(); }}public class RunnableImpl implements Runnable {
@Override public void run() {
//设置线程任务 System.out.println(Thread.currentThread().getName() + "这里是需要线程执行的任务代码"); }}

上面的代码中,我们创建了一个corePoolSize为5,任务队列为5,最大线程数量为10的线程池。

在这里插入图片描述
运行代码确实报了RejectedExecutionException异常。
  既然线程池的拒绝策略有4中,那么我们如何指定线程池使用哪种拒绝策略呢?

public class test03 {
public static void main(String[] args) {
//创建线程数为2的一个线程池 ThreadFactory threadFactory=r->new Thread(r,"这是工厂创建的线程---"); RejectedExecutionHandler handler = new DiscardPolicy(); ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 500, TimeUnit.MILLISECONDS, new ArrayBlockingQueue
(5),threadFactory,handler);// ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 500, TimeUnit.MILLISECONDS, new ArrayBlockingQueue
(5)); //提交需要执行的任务 for (int i = 0; i < 100; i++) {
threadPoolExecutor.execute(new RunnableImpl()); } //关闭线程池(注意:关闭线程池之后,线程也就不存在了,如果在关闭线程池之后又提交了需要执行的任务将会报错) threadPoolExecutor.shutdown(); }}

  通过上面重载ThreadPoolExrcutor构造方法可以自由指定我们想要使用的拒绝策略。上面得代码中,我们指定线程池使用DiscardPolicy策略,再次运行代码:

在这里插入图片描述

发现线程执行不会报RejectedExecutionException异常了。

转载地址:http://ejhwi.baihongyu.com/

你可能感兴趣的文章
射击游戏中跟踪弹及小角度移动的开发
查看>>
播放声音文件的完整源代码
查看>>
J2ME编程最佳实践之灵活的RMS应用
查看>>
MOBILE FIRST: HOW TO APPROACH MOBILE WEBSITE TESTING? 移动优先:如何处理移动网站测试?
查看>>
开始使用Retrofit 2 HTTP 客户端
查看>>
对于初学者练习的6个开源项目
查看>>
保持冷静和需要打破的东西:软件测试初学者
查看>>
如何通过连接您的业务应用程序来节省时间
查看>>
熟悉现代JavaScript的培训计划
查看>>
7本书从小工到数据分析专家
查看>>
程序设计的基本原则:栈和堆
查看>>
Android应用程序架构
查看>>
Android:绘制自定义视图
查看>>
Android开发:一些有用的库(第一部分)
查看>>
Android 默认暗码
查看>>
Android 系列 1.3了解Android版本
查看>>
Android 系列 6.28使用正确的复数格式化
查看>>
Android 系列 6.29创建在两个活动之间显示的加载屏幕
查看>>
Android的Gradle技巧 1.2配置SDK版本和其他默认值
查看>>
Android的Gradle技巧 1.3从命令行执行Gradle构建
查看>>