我的原則:先會用再說,內部慢慢來。
學以致用,根據場景學源碼
一、工具類 Executors
1.1 UML 圖
1.2 四個常用方法
方法 | 描述 |
---|---|
newCachedThreadPool | 創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。 (線程可複用) |
newFixedThreadPool | 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。 |
newScheduledThreadPool | 創建一個定長線程池,支持定時及週期性任務執行。 |
newSingleThreadExecutor | 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。 |
1.3 線程池的作用
- 提供了一個線程隊列,隊列中保存着所有等待狀態的線程。避免了創建與銷燬額外開銷,提高了相應速度。
二、實戰
2.1 newCachedThreadPool 方法
- java.util.concurrent.Executors#newCachedThreadPool() 方法,內部線程數量默認 Integer.MAX_VALUE ,線程池爲無限大。
- newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。
- 當執行第二個任務時第一個任務已經完成,會複用執行第一個任務的線程,而不用每次新建線程。
public static void method_newCachedThreadPool() {
// 1、創建線程池
ExecutorService pool = Executors.newCachedThreadPool();
// 2、分配任務
for (int i = 0; i < 20; i++) {
final int index = i;
pool.execute(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-" + index);
}
);
}
// 3、關閉線程池
pool.shutdown();
}
輸出:
pool-1-thread-2-1
pool-1-thread-9-8
pool-1-thread-10-9
pool-1-thread-1-0
pool-1-thread-12-11
pool-1-thread-14-13
pool-1-thread-15-14
pool-1-thread-17-16
pool-1-thread-18-17
pool-1-thread-19-18
pool-1-thread-20-19
pool-1-thread-8-7
pool-1-thread-13-12
pool-1-thread-6-5
pool-1-thread-7-6
pool-1-thread-3-2
pool-1-thread-5-4
pool-1-thread-16-15
pool-1-thread-4-3
pool-1-thread-11-10
2.2 newFixedThreadPool 方法
- java.util.concurrent.Executors#newFixedThreadPool(int)
- newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
public static void method_newFixedThreadPool() {
// 1、創建線程池
ExecutorService pool = Executors.newFixedThreadPool(4);
// 2、分配任務
for (int i = 0; i < 10; i++) {
final int index = i;
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "-" + index);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 3、關閉線程池
pool.shutdown();
}
- 因爲線程池大小爲4,每個任務輸出index後sleep 2秒,所以每兩秒打印4個數字。
- 輸出:
pool-1-thread-1-0
pool-1-thread-2-1
pool-1-thread-3-2
pool-1-thread-4-3
pool-1-thread-3-4
pool-1-thread-1-7
pool-1-thread-2-6
pool-1-thread-4-5
2.3 newScheduledThreadPool 方法
-
java.util.concurrent.Executors#newScheduledThreadPool(int) 規定池內線程最大數量
-
newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行。
public static void newScheduledThreadPoolSchedule() {
// 1、創建線程池
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
// 2、分配任務
// 啓動了兩個定時的任務,在JVM開啓後的1分鐘後,每隔2分鐘,開始執行一次。
LoopCount loopCount = new LoopCount();
for (int i = 0; i < 2; i++) {
final int index = i;
pool.scheduleAtFixedRate(() -> System.out.println(Thread.currentThread().getName() + "-" + index + "_count_" + loopCount.getCount().incrementAndGet()),
1, 2, TimeUnit.SECONDS);
}
}
@Data
static class LoopCount{
private AtomicInteger count = new AtomicInteger(0);
}
- 定時及週期性任務操作 scheduleAtFixedRate
- java.util.concurrent.ScheduledExecutorService#scheduleAtFixedRate 方法
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit)
- 啓動了兩個定時的任務,在JVM開啓後的1分鐘後,每隔2分鐘,開始執行一次。
- 輸出:
pool-1-thread-1-0_count_1
pool-1-thread-2-1_count_2
pool-1-thread-2-0_count_3
pool-1-thread-1-1_count_4
pool-1-thread-3-0_count_5
pool-1-thread-2-1_count_6
pool-1-thread-3-0_count_7
pool-1-thread-1-1_count_8
pool-1-thread-2-0_count_9
pool-1-thread-3-1_count_10
pool-1-thread-1-0_count_11
pool-1-thread-1-1_count_12
pool-1-thread-1-0_count_13
2.4 newSingleThreadExecutor 方法
- java.util.concurrent.Executors#newSingleThreadExecutor()
- 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
public static void method_newSingleThreadExecutor() {
// 1、創建線程池
ExecutorService pool = Executors.newSingleThreadExecutor();
// 2、分配任務
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
final int index = i;
pool.execute(() -> System.out.println(Thread.currentThread().getName() + "-" + index));
}
// 3、關閉線程池
pool.shutdown();
}
輸出:
pool-1-thread-1-0
pool-1-thread-1-1
pool-1-thread-1-2
pool-1-thread-1-3
pool-1-thread-1-4
pool-1-thread-1-5
pool-1-thread-1-6
pool-1-thread-1-7
pool-1-thread-1-8
pool-1-thread-1-9
- 結論:逐個輸出,先進先執行 FIFO。
=== 點擊查看top目錄 ===
三、番外篇
下一章節:【線程】ThreadPool 線程池底層剖析 (二十)
上一章節:【線程】Thread.UncaughtExceptionHandler 實戰與剖析 (十八)