[TOC]
線程池
1. 并發(fā)隊列:阻塞隊列和非阻塞隊列

區(qū)別如下:
入隊:
- 非阻塞隊列:當(dāng)隊列中滿了的時候,放入數(shù)據(jù),數(shù)據(jù)丟失
- 阻塞隊列:當(dāng)隊列滿了的時候,進(jìn)行等待,什么時候隊列中有出隊的數(shù)據(jù),那么第 11 個再放進(jìn)入
出隊:
- 非阻塞隊列:如果現(xiàn)在隊列中沒有元素,取數(shù)據(jù),得到的是 null
- 阻塞隊列:等待,什么時候放進(jìn)去,再取出來
線程池是使用阻塞隊列。
2. 線程池原理:ThreadPoolExecutor 底層原理解析
2. 1線程的生命周期
從出生到死亡的階段。

2.2 線程池工作原理
ThreadPoolExecutor t = new ThreadPoolExecutor(1, 3, 0, TimeUnit.MICROSECONDS, new LinkedBlockingDeque<>(3));
參數(shù)含義:
- 1:核心線程數(shù)
- 3:最大線程數(shù)
- 0 和
TimeUnit.MICROSECONDS:當(dāng)任務(wù)量大于隊列長度需要創(chuàng)建線程的時候,新創(chuàng)建的這個線程假如把隊列的任務(wù)都執(zhí)行完了,那么等待新任務(wù)的空閑時間就是這個 -
new LinkedBlockingDeque<>(3)):阻塞隊列:- 方法有參數(shù):隊列長度為 3
- 方法無參數(shù):隊列長度為
Integer.MAX_VALUE
執(zhí)行流程圖如下所示:

2.3 舉個例子
package com.test.jdk8;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestThreadPoolExecutor {
public static void main(String[] args) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 2, 3, TimeUnit.SECONDS, new LinkedBlockingDeque<>(3));
// 利用線程池里的線程,開始執(zhí)行任務(wù)
// 執(zhí)行第一個任務(wù)
pool.execute(new TestThread());
// 執(zhí)行下面三個任務(wù),放入阻塞隊列,阻塞隊列滿:
pool.execute(new TestThread());
pool.execute(new TestThread());
pool.execute(new TestThread());
// 執(zhí)行第 4個任務(wù),創(chuàng)建新線程,分?jǐn)側(cè)蝿?wù)
pool.execute(new TestThread());
// 執(zhí)行第 5 個任務(wù),創(chuàng)建新創(chuàng)建,線程數(shù)大于最大線程數(shù),報錯
pool.execute(new TestThread());
// 關(guān)閉線程池
pool.shutdown();
}
}
class TestThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
3. 線程池的分類
1. newCachedThreadPool 可緩存線程池
創(chuàng)建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。示例代碼如下:
package ThreadTest;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
// lambda 表達(dá)式, 實現(xiàn) new Runnable() 的 run() 方法
es.execute(() -> System.out.println(Thread.currentThread().getName()));
}
es.shutdown();
}
}
查看 newCachedThreadPool 源碼,可知:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
該線程池的核心線程數(shù)為 0, 最大線程數(shù)為 Integer.MAX_VALUE,將會根據(jù)需要創(chuàng)建新線程,新線程的數(shù)量不大于 Integer.MAX_VALUE,線程執(zhí)行任務(wù)結(jié)束后被釋放可重復(fù)使用該線程執(zhí)行另一個任務(wù)。
部分執(zhí)行結(jié)果如下:
pool-1-thread-6
pool-1-thread-11
pool-1-thread-6
pool-1-thread-10
pool-1-thread-4
pool-1-thread-11
pool-1-thread-2
2. newFixedThreadPool 定長線程池
創(chuàng)建一個定長線程池,可控制線程最大并發(fā)數(shù),超出的線程會在隊列中等待。示例代碼如下:
package ThreadTest;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(3);
for (int i = 0; i < 100; i++) {
// lambda 表達(dá)式, 實現(xiàn) new Runnable() 的 run() 方法
es.execute(() -> System.out.println(Thread.currentThread().getName()));
}
es.shutdown();
}
}
查看 newFixedThreadPool 源碼,可知:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
傳入的參數(shù)即為核心線程數(shù)和最大線程數(shù),核心線程數(shù)和最大線程數(shù)的數(shù)量是相等的。
所以上述示例代碼的執(zhí)行結(jié)果的線程數(shù)就為 3,部分執(zhí)行結(jié)果如下:
pool-1-thread-1
pool-1-thread-3
pool-1-thread-2
pool-1-thread-3
pool-1-thread-1
3. newScheduledThreadPool 定時線程池
創(chuàng)建一個定時線程池,支持定時及周期性任務(wù)執(zhí)行。延遲執(zhí)行示例代碼如下:
package ThreadTest;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
public static void main(String[] args) {
ScheduledExecutorService ses = Executors.newScheduledThreadPool(2);
for (int i = 0; i < 100; i++) {
ses.schedule(() -> System.out.println(Thread.currentThread().getName()), 3, TimeUnit.SECONDS);
}
ses.shutdown();
}
}
查看 newScheduledThreadPool 源碼,如下:
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
可知,newScheduledThreadPool 傳入的參數(shù)即為核心線程數(shù),最大線程數(shù)為 Integer.MAX_VALUE。
上述代碼通過設(shè)置延遲參數(shù) 3, 單位 TimeUnit.SECONDS,延遲三秒后執(zhí)行任務(wù),創(chuàng)建的線程數(shù)為 2。執(zhí)行部分結(jié)果如下:
pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
pool-1-thread-2
pool-1-thread-1
4. newSingleThreadExecutor 單例線程池
創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行。示例代碼如下:
package ThreadTest;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Test {
public static void main(String[] args) {
ExecutorService es = Executors.newSingleThreadExecutor();
for (int i = 0; i < 100; i++) {
es.execute(() -> System.out.println(Thread.currentThread().getName()));
}
es.shutdown();
}
}
查看 newSingleThreadExecutor 源碼,可知:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
核心線程數(shù)和最大線程數(shù)都為 1,執(zhí)行完任務(wù)后線程的存活時間為 0,即創(chuàng)建出來的線程只會執(zhí)行一次任務(wù),保證單例執(zhí)行。
運行部分結(jié)果如下:
pool-1-thread-1
pool-1-thread-1
pool-1-thread-1