摘要:本文主要向大家介绍了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频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号