- AbortPolicy: 拒绝策略,不指定为默认值
- CallerRunsPolicy: 在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务
- DiscardPolicy: 放弃策略,线程池拒绝的任务直接抛弃,不会抛异常也不会执行
- DiscardOldestPolicy: 任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。
AbortPolicy(拒绝策略)为默认值
源码:可以看到直接抛出运行异常
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
测试代码:
public class Test {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0
,TimeUnit.MICROSECONDS
,new ArrayBlockingQueue<>(2,true)
,new ThreadPoolExecutor.AbortPolicy()); // 拒绝策略
for (int i = 1; i <= 10; i++) {
System.out.println("添加第"+i+"个线程");
executor.execute(new MyThread("线程"+i));
Iterator iterator = executor.getQueue().iterator();
if (iterator.hasNext()) {
while (iterator.hasNext()) {
MyThread thread = (MyThread) iterator.next();
System.out.println("队列queue中:" + thread.name);
}
}else {
System.out.println("队列中为null");
}
}
}
// 内部类 主要是为线程起名称方便观察
static class MyThread implements Runnable {
String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程:" + Thread.currentThread().getName() + " 执行:" + name + " run");
}
}
}
运行结果乳如下:
添加第1个线程
队列中为null
添加第2个线程
队列queue中:线程2
添加第3个线程
队列queue中:线程2
队列queue中:线程3
添加第4个线程
队列queue中:线程2
队列queue中:线程3
添加第5个线程
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task Test$MyThread@593634ad rejected from java.util.concurrent.ThreadPoolExecutor@20fa23c1[Running, pool size = 2, active threads = 2, queued tasks = 2, completed tasks = 0]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at Test.main(Test.java:33)
线程:pool-1-thread-2 执行:线程4 run
线程:pool-1-thread-1 执行:线程1 run
线程:pool-1-thread-1 执行:线程3 run
线程:pool-1-thread-2 执行:线程2 run
分析运行结果:
1.添加第一个任务时,直接执行
此时队列中:null
2.添加第二个任务时,由于线程核心数为"1"并且核心线程被占用,所以被加入到队列中
此时队列中:任务二
3.添加第三个任务时同上
此时队列中:任务二、任务三
4.添加第四个任务时,因为核心任务还在运行,而且任务队列已经满了,所以直接创建新线程执行第四个任务
此时队列中:任务二、任务三
5.添加第五个任务时,因为 maxPoolSize为2 + 队列BlockingQueue容量为2 = 4 也就是最大承载为4个线程所以执行拒绝策略的rejectedExecution方法,这里就是执行AbortPolicy的rejectedExecution方法直接抛出异常
6.最终,只有四个线程能完成运行。后面的都被拒绝了。
CallerRunsPolicy
源码:当发生拒绝是,调用当前线程池的所在的线程去执行被拒绝的任务
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
测试代码:其它同上
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0
,TimeUnit.MICROSECONDS
,new ArrayBlockingQueue<>(2,true)
,new ThreadPoolExecutor.AbortPolicy()); // 在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务
运行结果:
添加第1个线程
队列中为null
添加第2个线程
队列queue中:线程2
添加第3个线程
队列queue中:线程2
队列queue中:线程3
添加第4个线程
队列queue中:线程2
队列queue中:线程3
添加第5个线程
线程:main 执行:线程5 run
队列queue中:线程2
队列queue中:线程3
添加第6个线程
线程:pool-1-thread-2 执行:线程4 run
线程:pool-1-thread-1 执行:线程1 run
线程:pool-1-thread-1 执行:线程3 run
线程:main 执行:线程6 run
队列中为null
添加第7个线程
线程:pool-1-thread-2 执行:线程2 run
队列queue中:线程7
添加第8个线程
队列queue中:线程8
添加第9个线程
队列queue中:线程8
队列queue中:线程9
添加第10个线程
队列queue中:线程8
队列queue中:线程9
线程:pool-1-thread-2 执行:线程7 run
线程:pool-1-thread-3 执行:线程10 run
线程:pool-1-thread-2 执行:线程8 run
线程:pool-1-thread-3 执行:线程9 run
分析结果:
添加第五个任务,任务5的时候,同样被线程池拒绝了,因此执行了CallerRunsPolicy的rejectedExecution方法,
这个方法直接执行任务的run方法.因此可以看到任务5是在main线程中执行的
这个策略的缺点就是可能会阻塞主线程。
DiscardPolicy(放弃策略)
源码:被线程池拒绝的任务直接抛弃,不会抛异常也不会执行。
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
测试代码:其它同上
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0
,TimeUnit.MICROSECONDS
,new ArrayBlockingQueue<>(2,true)
,new ThreadPoolExecutor.DiscardPolicy());
//线程池拒绝的任务直接抛弃,不会抛异常也不会执行。
运行结果:
添加第1个线程
队列中为null
添加第2个线程
队列queue中:线程2
添加第3个线程
队列queue中:线程2
队列queue中:线程3
添加第4个线程
队列queue中:线程2
队列queue中:线程3
添加第5个线程
队列queue中:线程2
队列queue中:线程3
添加第6个线程
队列queue中:线程2
队列queue中:线程3
添加第7个线程
队列queue中:线程2
队列queue中:线程3
添加第8个线程
队列queue中:线程2
队列queue中:线程3
添加第9个线程
队列queue中:线程2
队列queue中:线程3
添加第10个线程
队列queue中:线程2
队列queue中:线程3
线程:pool-1-thread-1 执行:线程1 run
线程:pool-1-thread-2 执行:线程4 run
线程:pool-1-thread-1 执行:线程2 run
线程:pool-1-thread-2 执行:线程3 run
分析结果:
只有四个任务被执行了,其他什么反应都没有,直接丢弃。
DiscardOldestPolicy(放弃最早策略)
源码:在rejectedExecution先从任务队列总弹出最先加入的任务,空出一个位置,然后再次执行execute方法把任务加入队列。
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
测试代码:其它同上
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 2, 0
,TimeUnit.MICROSECONDS
,new ArrayBlockingQueue<>(2,true)
,new ThreadPoolExecutor.DiscardOldestPolicy());
运行结果:
添加第1个线程
队列中为null
添加第2个线程
队列queue中:线程2
添加第3个线程
队列queue中:线程2
队列queue中:线程3
添加第4个线程
队列queue中:线程2
队列queue中:线程3
添加第5个线程
队列queue中:线程3
队列queue中:线程5
添加第6个线程
队列queue中:线程5
队列queue中:线程6
添加第7个线程
队列queue中:线程6
队列queue中:线程7
添加第8个线程
队列queue中:线程7
队列queue中:线程8
添加第9个线程
队列queue中:线程8
队列queue中:线程9
添加第10个线程
队列queue中:线程9
队列queue中:线程10
线程:pool-1-thread-2 执行:线程4 run
线程:pool-1-thread-1 执行:线程1 run
线程:pool-1-thread-2 执行:线程10 run
线程:pool-1-thread-1 执行:线程9 run
分析结果:
可以看到线程9和线程10顶替了线程2和线程3的位子,其他线程被放弃,既不运行也不抛异常