• 线程池拒绝策略


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

    拒绝策略

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

    public ThreadPoolExecutor(int corePoolSize,
                                  int maximumPoolSize,
                                  long keepAliveTime,
                                  TimeUnit unit,
                                  BlockingQueue<Runnable> 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<Runnable>(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<Runnable>(5),threadFactory,handler);
    //		ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 500, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(5));
    
    		//提交需要执行的任务
    		for (int i = 0; i < 100; i++) {
    			threadPoolExecutor.execute(new RunnableImpl());
    		}
    		//关闭线程池(注意:关闭线程池之后,线程也就不存在了,如果在关闭线程池之后又提交了需要执行的任务将会报错)
    		threadPoolExecutor.shutdown();
    	}
    }
    

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

    在这里插入图片描述
    发现线程执行不会报RejectedExecutionException异常了。

  • 相关阅读:
    Intellij IDEA 使用总结
    Apache Camel之FTP组件学习
    谈一谈EasyUI中TreeGrid的过滤功能
    JAVA实用案例之图片水印开发
    三、SolrCloud的搭建
    style里面设置变量
    for 循环中 break-continue 与label标签的使用
    vue ref的用法
    Vuex实践
    vue 数据动态响应(Vue.set方法)
  • 原文地址:https://www.cnblogs.com/wgty/p/12810473.html
Copyright © 2020-2023  润新知