- 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的位子,其他線程被放棄,既不運行也不拋異常