最近準備詳細的複習下Java線程池相關的所以知識。就從我們最初使用線程池開始,也就是Executors,慢慢展開。
0x01先談談爲什麼要使用線程池
第一:降低資源消耗。通過重複利用已創建的線程降低線程創建和銷燬造成的消耗。
第二:提高響應速度。當任務到達時,任務可以不需要等到線程創建就能立即執行。
第三:提高線程的可管理性。線程是稀缺資源,如果無限制的創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一的分配,調優和監控
線程池對線程的管理性體現在:
- 創建和銷燬由線程池管理,能夠設置非核心線程的存活時間。
- 能夠控制最大線程數
- 提供定時執行的功能
0x02關於Executors類
首先:這貨就是個工具類,封裝了大部分我們常用到的線程池相關方法。
此類中包含了Executor,ExecutorService,ScheduledExecutorService,ThreadFactory和Callable類的工廠和utils方法。
此類支持以下方法:
- 使用常用的配置進行設置,創建和返回ExecutorService
- 使用常用的配置進行設置,創建和返回ScheduledExecutorService
- 創建並返回“包裝”ExecutorService,該ExecutorService通過使特定的方法無法訪問,來禁止重新配置。
- 創建並返回ThreadFactory,該ThreadFactory其能夠根據指定狀態創建的新線程。
- 從類似閉包形式創建和返回Callable,可以在需要Callable的執行方法中使用它們。
0x03怎麼使用線程池
Java中的線程池實現了Executor和ExecutorService接口,可以使用以下四種方法添加runnable任務:
void execute(Runnable command);
Future<?> submit(Runnable task);
<T> Future<T> submit(Runnable task, T result);
<T> Future<T> submit(Callable<T> task);
//後面三種方法都會返回一個Future對象,使得我們可以獲取任務執行的狀態。
上面爲什麼是用的“添加”,而不是“執行”呢?因爲調用execute或submit方法之後,任務只是被添加到線程池的阻塞隊列中,然後等待空閒線程的來執行。如果阻塞隊列滿了,並且線程池中的線程數也達到了設置的最大值,那麼此時線程池飽和,任務無法添加,會被Reject。具體的Reject後面文章再談。