創(chuàng)建線程池的方式:
使用Java提供的用于管理線程池的接口ExecutorService 創(chuàng)建線程池,共有四種方式:
Executors.newCachedThreadPool();
Executors.newFixedThreadPool(10);
Executors.newScheduledThreadPool(10);
Executors.newSingleThreadExecutor();
// 獲取當前主機的處理器cpu的可用個數,可根據該參數來修改線程池的大小
System.out.println("處理器的可用個數:" + Runtime.getRuntime().availableProcessors());
1窄做、 newCachedThreadPool
創(chuàng)建一個可根據需要創(chuàng)建新線程的線程池队询,在以前創(chuàng)建的線程可用時重用它們。該線程池可緩存泼差,無限大贵少。
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
});
}
}
源碼:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
// 上面返回的對象指向下面的 ThreadPoolExecutor(...) 構造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
參數的意義:
- corePoolSize :核心線程池的數量
- maximumPoolSize :線程池的最大數量, Integer.MAX_VALUE 可以看作是無限的
- keepAliveTime : 線程保持活躍狀態(tài)的時間
- unit : 時間單位
- workQueue : 工作隊列堆缘,SynchronousQueue 是一個不存儲元素的隊列滔灶,可以理解為隊列已滿
根據上面的源碼可知:
當調用該方法創(chuàng)建線程池時,workQueue 為0吼肥,不創(chuàng)建核心線程宽气,且隊列已滿,因此會創(chuàng)建非核心線程執(zhí)行任務潜沦。對于非核心線程空閑60s就會被回收萄涯,而線程池的數量幾乎是無限的,當資源有限時易引起OOM異常唆鸡。
2涝影、newFixedThreadPool
創(chuàng)建一個可重用固定線程集合的線程池,以共享的無界隊列方式運行線程争占。
定長的線程池燃逻,可控制線程最大并發(fā)數,超出的線程會在隊列中等待臂痕。
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
});
}
}
源碼:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
// 上面返回的對象指向下面的 ThreadPoolExecutor(...) 構造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
說明
參數與SingleThreadExecutor 一致伯襟,區(qū)別是核心線程數是由用戶傳入的。
3握童、newSingleThreadExecutor
創(chuàng)建一個使用單個worker線程的線程池姆怪,以無界隊列的方式運行。
該線程池只存在一個線程澡绩,會按照順序執(zhí)行稽揭,不同與單線程。
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
});
}
}
源碼:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
// 上面返回的對象指向下面的 ThreadPoolExecutor(...) 構造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
說明
返回的核心線程池數量為1肥卡,最大線程池數量為1溪掀,即只能創(chuàng)建一個非核心線程。
4步鉴、newScheduledThreadPool
創(chuàng)建一個線程池揪胃,可安排在給定延遲后運行命令或定期執(zhí)行璃哟。
定長線的程池,支持定時及周期性任務執(zhí)行喊递。
public static void main(String[] args) {
ExecutorService executorService = Executors.newScheduledThreadPool(10);
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
});
}
}
源碼:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
// 上面返回的對象指向下面的構造方法
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
// 查看ScheduledThreadPoolExecutor 的類沮稚,發(fā)現其繼承了ThreadPoolExecutor,并實現了ScheduledExecutorService接口
public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService {...}
// 繼續(xù)追蹤父類的構造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
// this(...)方法對應的如下:
public ThreadPoolExecutor(int corePoolSize, // 核心線程池數量
int maximumPoolSize, // 最大線程數
long keepAliveTime, // 保持線程存活時間
TimeUnit unit, // 時間單位
BlockingQueue<Runnable> workQueue, // 保存任務的阻塞隊列
ThreadFactory threadFactory, // 創(chuàng)建線程的工廠
RejectedExecutionHandler handler) { // 拒接策略
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
其他方式
// 通過ScheduledExecutorService(繼承了ExecutorService)接口册舞,調用schedule方法蕴掏,通過該方法中的參數設置可以設置執(zhí)行時間。
// 該方法的第二個调鲸、第三個參數結合設置從當前開始推遲設置的時間來執(zhí)行
public static void main(String[] args) {
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 10; i++) {
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getId());
}
}, 3, TimeUnit.SECONDS);
}
}