1. 什么是線程池?
線程池其實就是將多個線程對象放到一個容器當中。
2. 為什么使用線程池?
可以重用線程,減少創(chuàng)建和銷毀線程帶來的消耗。
3. 如何使用線程池?
要想知道如何使用線程池,就要先知道線程池的種類有多少種?線程池大概有以下幾種:
- ThreadPoolExecutor
- FixedThreadPool
- CahcedThreadPool
- SingleThreadExecutor
- ScheduledThreadPool
以下介紹這幾種線程池的用法:
3.1 ThreadPoolExecutor
ThreadPoolExecutor 是線程池真正的實現(xiàn)方法,以下是 ThreadPoolExecutor 的構造方法:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
它需要傳入一系列參數(shù)來配置線程池,下面介紹每個參數(shù)的意義。
| 參數(shù) | 意義 |
|---|---|
| corePoolSize | 線程池的核心線程數(shù) |
| maximumPoolSize | 線程池容納最大的線程數(shù) |
| keepAliveTime | 非核心線程閑置時的超時時長 |
| unit | keepAliveTime 參數(shù)的時間單位 |
| workQueue | 線程池中的任務隊列 |
| threadFactory | 線程工廠,為線程池提供創(chuàng)建新線程的功能 |
3.2 FixedThreadPool
一種固定線程數(shù)量的線程池。
可以通過 Executors 的 newFixedThreadPool() 方法創(chuàng)建:
ExecutorService pool = Executors.newFixedThreadPool(4);
newFixedThreadPool() 具體實現(xiàn):
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
可以看出 newFixedThreadPool() 是通過創(chuàng)建 ThreadPoolExecutor 來創(chuàng)建線程池的。
并且因為 corePoolSize 和 maximumPoolSize 是一樣的,所以這種線程池只有核心線程,任務超出線程數(shù)后,會在隊列中等待。
具體使用如下:
ExecutorService pool = Executors.newFixedThreadPool(4);
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("haha");
}
};
pool.execute(task);
3.3 CahcedThreadPool
一種線程數(shù)量不定的線程池。
可以通過 Executors 的 newCachedThreadPool() 方法創(chuàng)建:
ExecutorService pool = Executors.newCachedThreadPool();
newCachedThreadPool() 具體實現(xiàn):
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
可以看到 corePoolSize 為 0,maximumPoolSize 為 Integer.MAX_VALUE,證明這種線程池沒有核心線程,但是有多個非核心線程。
這種線程池的特點就是,當有任務提交時,如果有空閑線程則復用空閑線程,沒有的話就新建線程處理。
空閑線程如果超過 60 秒就會被回收。
具體使用如下:
ExecutorService pool = Executors.newCachedThreadPool();
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("haha");
}
};
pool.execute(task);
3.4 SingleThreadExecutor
一種只有一個工作線程的線程池。
可以通過 Executors 的 newSingleThreadExecutor() 方法創(chuàng)建:
ExecutorService pool = Executors.newSingleThreadExecutor();
newSingleThreadExecutor() 具體實現(xiàn):
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
從源碼可以看出,這種線程池只有一個核心線程,并且總線程數(shù)為 1。
具體使用如下:
ExecutorService pool = Executors.newSingleThreadExecutor();
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("haha");
}
};
pool.execute(task);
3.5 ScheduledThreadPool
一種核心線程數(shù)量固定,非核心線程數(shù)不固定的線程池。
可以通過 Executors 的 newScheduledThreadPool() 方法創(chuàng)建:
ExecutorService pool = Executors.newScheduledThreadPool(4);
newScheduledThreadPool() 具體實現(xiàn):
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
// DEFAULT_KEEPALIVE_MILLIS = 10L
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
// 進去 super 的代碼
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
從源碼可以看出這種線程池的核心線程是固定的,非核心線程數(shù)沒有限制,但是非核心線程出現(xiàn)空閑后,10 毫秒就會被回收。
具體使用:
ExecutorService pool = Executors.newFixedThreadPool(4);
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("haha");
}
};
// 1 秒后執(zhí)行任務
pool.schedule(task, 1, TimeUnit.SECONDS);
// 延遲 10 毫秒后,每隔 2000 毫秒執(zhí)行一次任務
pool.scheduleAtFixedRate(task, 10,2000, TimeUnit.MICROSECONDS);