JAVA语言并发编程实战教程之线程池的饱和策略
小标 2018-09-11 来源 : 阅读 1223 评论 0

摘要:本文主要向大家介绍了JAVA语言并发编程实战教程之线程池的饱和策略,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

本文主要向大家介绍了JAVA语言并发编程实战教程之线程池的饱和策略,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助。

通常情况下,线程池会判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。但是如果有限队列已经满了,则会交给饱和策略来处理这个任务。

ThreadPoolExecutor 的饱和策略可以通过调用 setRejectedExecutionHandler 来修改。JDK 提供了下面几种不同的饱和策略。

AbortPolicy

CallerRunsPolicy

DiscardPolicy

DiscardOldestPolicy

下面我们举例来逐个来说明,先看下面代码,我们创建一个线程池,然后创建一个函数 getPolicy() 用于获取不同的饱和策略。通过传入不同的饱和策略参数变量选择不同的策略,通过执行结果来检查饱和策略的效果。

import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;import java.util.concurrent.Callable;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingDeque;import java.util.concurrent.RejectedExecutionException;import java.util.concurrent.RejectedExecutionHandler;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;public class ThreadPoolRejectedPolicyTest{

   //线程池大小
   private static final int THREAD_SIZE = 2;    //任务数量
   private static final int TASK_SIZE = 5;    //饱和策略
   private static final int ABORT_POLICY = 0;//Abort 策略
   private static final int CALLER_RUNS_POLICY = 1;//CallerRuns 策略
   private static final int DISCARD_POLICY = 2;//Discard策略
   private static final int DISCARD_OLDEST_POLICY = 3;//DiscardOlds策略

   //策略选择变量,改这个值选择不同的饱和策略
   private static int selectedPolicy = ABORT_POLICY;    @SuppressWarnings("unchecked")    public static void main(String[] args) {        //阻塞队列只能容纳一个任务
       BlockingQueue Q = new LinkedBlockingDeque<>(1);        //创建一个固定线程的线程池
       ThreadPoolExecutor service = new ThreadPoolExecutor(THREAD_SIZE,THREAD_SIZE,0L, TimeUnit.MILLISECONDS,Q);        //设置线程池的饱和策略
       service.setRejectedExecutionHandler(getPolicy(selectedPolicy));        //提交任务
       for(int i = 0; i < TASK_SIZE; i++) {
           service.submit(new Task(i));
       }
       service.shutdown();
   }    //任务
   static class Task implements Runnable {        //任务ID
       private int taskId;        public Task(int id) {
           taskId = id;
       }        @Override
       public void run() {            try {
               Thread.sleep(50);
           } catch (InterruptedException e) {
               System.err.println("线程被中断" + e.getMessage());  
           }            //打印当前任务信息
           System.out.println("Task " + taskId + " is running on " + Thread.currentThread().getName());
       }
   }    //饱和策略
   static RejectedExecutionHandler getPolicy(int policy) {        switch (policy) {        case ABORT_POLICY:            return new ThreadPoolExecutor.AbortPolicy();        case CALLER_RUNS_POLICY:            return new ThreadPoolExecutor.CallerRunsPolicy();        case DISCARD_POLICY:            return new ThreadPoolExecutor.DiscardPolicy();        case DISCARD_OLDEST_POLICY:            return new ThreadPoolExecutor.DiscardOldestPolicy();        default:            break;
       }        return new ThreadPoolExecutor.AbortPolicy();
   }
}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879

AbortPolicy

将上面代码的变量 selectedPolicy 设置为 ABORT_POLICY。

selectedPolicy = ABORT_POLICY1

运行程序,执行结果如下:

如上所示,执行了三个任务,第四个提交的时候,直接抛出异常,并且JVM一直处于运行状态。任务0和任务1已提交就被线程池中的两个线程执行,任务2提交到阻塞队列等待执行,这个时候继续提交任务,由于队列已满,触发饱和策略,直接抛出异常。

CallerRunsPolicy

将上面代码的变量 selectedPolicy 设置为 CALLER_RUNS_POLICY。

selectedPolicy = CALLER_RUNS_POLICY1

运行程序,执行结果如下: 

如上所示,所有任务都被执行,不会被抛弃也不会有异常抛出。任务0,1,2都在线程池中的线程执行。任务3,4则是由main线程执行。这说明,CallerRunsPolicy 饱和策略在队列已满的情况下,会把后面提交的任务给回调用者线程去执行。换句话说就是在调用exector的线程中运行新的任务。

DiscardPolicy

将上面代码的变量 selectedPolicy 设置为 DISCARD_POLICY。

selectedPolicy = DISCARD_POLICY1

运行程序,执行结果如下: 

如上所示,只执行了任务0,1,3。其他任务直接被抛弃。所以 DiscardPolicy 正如其名字,简单粗暴,队列满后新任务通通都抛弃。

DiscardOldestPolicy

将上面代码的变量 selectedPolicy 设置为 DISCARD_OLDEST_POLICY。

selectedPolicy = DISCARD_OLDEST_POLICY1

运行程序,执行结果如下: 

如上所示,只执行了任务0,1,4。其他任务2,3直接被抛弃。所以 DiscardOldestPolicy 也可以说正如其名字,简单粗暴,队列满后等待最久的任务将被新任务替换。

以上就是 JDK 提供的四个饱和策略,本文到此完结。


本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注编程语言JAVA频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程