import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
* @description: 測試使用線程池
*/
public class TestThreadPool {
public static void main(String[] args) {
//核心線程個數
int corePoolSize = 2;
//最大線程數量
int maximumPoolSize = 4;
//創(chuàng)建了超出核心線程個數的線程(臨時線程)后,當該線程空閑下來可能會被銷毀
//線程允許空閑時間(線程在空閑狀態(tài)下,在允許空閑時間內不會銷毀)
//TimeUnit表示允許線程空閑時間的單位
long keepAliveTime = 1L;
//等待隊列
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1024);
//線程池飽和策略
RejectedExecutionHandler policy = new RejectedDiscardPolicy("taskId");
ExecutorService executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, queue, policy);
for (int i = 0; i < 100000; i++) {
executor.execute(new Worker());
}
//慎用shutdownNow(立即關閉線程池,不管隊列中的任務是否執(zhí)行完)
// executorService.shutdownNow();
//推薦使用shutdown去關閉線程池,這個方法會等待隊列中的任務全部執(zhí)行完才去關閉線程池
executor.shutdown();
}
}
class Worker implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在執(zhí)行");
}
}
/**
* @description: 自定義飽和策略(中止策略也是默認策略)
*/
class RejectedAbortPolicy implements RejectedExecutionHandler {
/**
* 執(zhí)行任務的標識
*/
private String taskId;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public RejectedAbortPolicy(String taskId) {
this.taskId = taskId;
}
/**
* @description: 使用該策略時在飽和時會拋出RejectedExecutionException(繼承自RuntimeException),調用者可捕獲該異常自行處理。
*/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
throw new RejectedExecutionException(taskId +
" rejected from " +
executor.toString());
}
}
/**
* @description: 自定義飽和策略(拋棄策略)
*/
class RejectedDiscardPolicy implements RejectedExecutionHandler {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 執(zhí)行任務的標識
*/
private String taskId;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public RejectedDiscardPolicy(String taskId) {
this.taskId = taskId;
}
/**
* @description: 不做任何處理直接拋棄任務
*/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
//計劃執(zhí)行的大致任務數
String taskCount = String.valueOf(executor.getTaskCount());
//正在執(zhí)行任務的大致線程數
String activeCount = String.valueOf(executor.getActiveCount());
//不處理使用拋棄策略
logger.error("RejectedDiscardPolicy.rejectedExecution, taskId :{}, task count: {}, active thread: {}", taskId,
taskCount, activeCount);
}
}
/**
* @description: 自定義飽和策略(拋棄舊任務策略)
*/
class RejectedDiscardOldestPolicy implements RejectedExecutionHandler {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 執(zhí)行任務的標識
*/
private String taskId;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public RejectedDiscardOldestPolicy(String taskId) {
this.taskId = taskId;
}
/**
* @description: 先將阻塞隊列中的當前任務拋棄,再嘗試提交任務。如果此時阻塞隊列使用PriorityBlockingQueue優(yōu)先級隊列,將會導致優(yōu)先級最高的任務被拋棄,因此不建議將該種策略配合優(yōu)先級隊列使用。
*/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (!executor.isShutdown()) {
executor.getQueue().poll();
executor.execute(r);
}
logger.error("RejectedDiscardOldestPolicy.rejectedExecution,taskId:{}", taskId);
}
}
/**
* @description: 自定義飽和策略(調用者運行)
*/
class RejectedCallerRunsPolicy implements RejectedExecutionHandler {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 執(zhí)行任務的標識
*/
private String taskId;
public String getTaskId() {
return taskId;
}
public void setTaskId(String taskId) {
this.taskId = taskId;
}
public RejectedCallerRunsPolicy(String taskId) {
this.taskId = taskId;
}
/**
* @description: 既不拋棄任務也不拋出異常,直接運行任務的run方法,換言之將任務回退給調用者來直接運行。
* 使用該策略時線程池飽和后將由調用線程池的主線程自己來執(zhí)行任務,
* 因此在執(zhí)行任務的這段時間里主線程無法再提交新任務,從而使線程池中工作線程有時間將正在處理的任務處理完成。
*/
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (!executor.isShutdown()) {
r.run();
}
logger.warn("RejectedCallerRunsPolicy.rejectedExecution,taskId:{}", taskId);
}
}
juc - 線程池的使用
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
相關閱讀更多精彩內容
- 這是一篇 寫的非常用心的 博文,這里是原文地址https://blog.csdn.net/l540675759/a...
- 1、簡介:1.1 iOS有三種多線程編程的技術,分別是:1.、NSThread2、Cocoa NSOperatio...
- Executors為Executor,ExecutorService,ScheduledExecutorServi...
- 原文連接 在前面的文章中,我們使用線程的時候就去創(chuàng)建一個線程,這樣實現起來非常簡便,但是就會有一個問題: 如果并發(fā)...