java bus Java并發——阿里架構師
一、創建線程
1.創建普通對象,只是在JVM的堆里分配一塊內存而已
2.創建線程,需要調用操作系統內核的API,然后操作系統需要為線程分配一系列資源,成本很高
線程是一個重量級對象,應該避免頻繁創建和銷毀,采用線程池方案
二、一般的池化資源
// 假設Java線程池采用一般意義上池化資源的設計方法
class ThreadPool {
// 獲取空閑線程
Thread acquire() {
}
// 釋放線程
void release(Thread t) {
}
}
// 期望的使用
ThreadPool pool;
Thread T1 = pool.acquire();
// 傳入Runnable對象
T1.execute(() -> {
// 具體業務邏輯
});
三、生產者-消費者模式
業界線程池的設計,普遍采用生產者-消費者模式,線程池的使用方是生產者,線程池本身是消費者
public class MyThreadPool {
// 工作線程負責消費任務并執行任務
class WorkerThread extends Thread {
@Override
public void run() {
// 循環取任務并執行
while (true) {
Runnable task = null;
try {
task = workQueue.take();
} catch (InterruptedException e) {
}
task.run();
}
}
}
// 利用阻塞隊列實現生產者-消費者模式
private BlockingQueue workQueue;
// 內部保存工作線程
List threads = new ArrayList<>();
public MyThreadPool(int poolSize, BlockingQueue workQueue) {
this.workQueue = workQueue;
for (int i = 0; i < poolSize; i++) {
WorkerThread work = new WorkerThread();
work.start();
threads.add(work);
}
}
// 提交任務
public void execute(Runnable command) throws InterruptedException {
workQueue.put(command);
}
public static void main(String[] args) throws InterruptedException {
// 創建有界阻塞隊列
BlockingQueue workQueue = new LinkedBlockingQueue<>(2);
// 創建線程池
MyThreadPool pool = new MyThreadPool(10, workQueue);
// 提交任務
pool.execute(() -> {
System.out.println("hello");
});
}
}
四、Java線程池
Ⅰ. ThreadPoolExecutor
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
// 讓所有線程都支持超時,如果線程池很閑,那么將撤銷所有線程
public void allowCoreThreadTimeOut(boolean value)
1.corePoolSize:線程池保有的最小線程數
2.maximumPoolSize:線程池創建的最大線程數
3.keepAliveTime & unit
如果一個線程空閑了keepAliveTime & unit,并且線程池的線程數大于corePoolSize,那么這個空閑的線程就要被回收
4.workQueue:工作隊列
5.threadFactory:自定義如何創建線程
6.handler
線程池中的所有線程都很忙碌,并且工作隊列也滿了(工作隊列是有界隊列),此時提交任務,線程池會拒絕接收
CallerRunsPolicy:提交任務的線程自己去執行該任務
AbortPolicy:默認的拒絕策略,拋出RejectedExecutionException
DiscardPolicy:直接丟棄任務,不會拋出任何異常
DiscardOldestPolicy:丟棄最老的任務,然后把新任務加入到工作隊列中
Ⅱ. Executors
1.不建議使用Executors,因為Executors提供的很多默認方法使用的是無界隊列LinkedBlockingQueue
2.在高負載的情況下,無界隊列容易導致OOM,而OOM會導致所有請求都無法處理
3.因此強烈建議使用有界隊列
Ⅲ. 拒絕策略
1.使用有界隊列,當任務過多時,線程池會觸發拒絕策略
2.線程池默認的拒絕策略會拋出RejectedExecutionException,這是一個運行時異常,開發時很容易忽略
3.如果線程池處理的任務非常重要,可以自定義拒絕策略
Ⅳ. 異常處理
1.使用ThreadPoolExecutor.execute()方法提交任務時,如果任務在執行過程中出現運行時異常
會導致執行任務的線程終止,并且無法獲得任何通知
2.因此最穩妥的方法還是捕獲所有異常并處理
try {
// 業務邏輯
} catch (RuntimeException x) {
// 按需處理
} catch (Throwable x) {
// 按需處理
}
免責聲明:本網站內容主要來自原創、合作媒體供稿和第三方自媒體作者投稿,凡在本網站出現的信息,均僅供參考。本網站將盡力確保所提供信息的準確性及可靠性,但不保證有關資料的準確性及可靠性,讀者在使用前請進一步核實,并對任何自主決定的行為負責。本網站對有關資料所引致的錯誤、不確或遺漏,概不負任何法律責任。任何單位或個人認為本網站中的網頁或鏈接內容可能涉嫌侵犯其知識產權或存在不實內容時,應及時向本網站提出書面權利通知或不實情況說明,并提供身份證明、權屬證明及詳細侵權或不實情況證明。本網站在收到上述法律文件后,將會依法盡快聯系相關文章源頭核實,溝通刪除相關內容或斷開相關鏈接。
新聞排行榜
-
2021-01-21 11:23
-
2018-09-28 11:33
-
2018-09-28 11:33
-
2018-09-28 11:33
-
2018-09-28 11:33
新聞熱門推薦
-
2021-01-21 11:23
-
2018-09-28 11:33
-
2018-09-28 11:33
-
2018-09-28 11:33
-
2018-09-28 11:33