首先,看一下這種線程池的建立方法:緩存
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
複製代碼
從構造方法能夠看出,它建立了一個固定大小的線程池,每次提交一個任務就建立一個線程,直到線程達到線程池的最大值nThreads。線程池的大小一旦達到最大值後,再有新的任務提交時則放入無界阻塞隊列中,等到有線程空閒時,再從隊列中取出任務繼續執行。 那麼,如何使用newFixedThreadPool呢?咱們來舉個例子:bash
public class OneMoreStudy {
public static void main(String[] args) {
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 5; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat(
"HH:mm:ss");
System.out.println("運行時間: " +
sdf.format(new Date()) + " " + index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
fixedThreadPool.shutdown();
}
}
複製代碼
上面的例子中建立了一個固定大小爲3的線程池,而後在線程池提交了5個任務。在提交第4個任務時,由於線程池的大小已經達到了3而且前3個任務在運行中,因此第4個任務被放入了隊列,等待有空閒的線程時再被運行。運行結果以下(注意前3個任務和後2個任務的運行時間):異步
運行時間: 08:09:02 1
運行時間: 08:09:02 2
運行時間: 08:09:02 0
運行時間: 08:09:04 4
運行時間: 08:09:04 3
複製代碼
首先,看一下這種線程池的建立方法:ide
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
複製代碼
從構造方法能夠看出,它建立了一個可緩存的線程池。當有新的任務提交時,有空閒線程則直接處理任務,沒有空閒線程則建立新的線程處理任務,隊列中不儲存任務。線程池不對線程池大小作限制,線程池大小徹底依賴於操做系統(或者說JVM)可以建立的最大線程大小。若是線程空閒時間超過了60秒就會被回收。 那麼,如何使用newCachedThreadPool呢?咱們來舉個例子:ui
public class OneMoreStudy {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 5; i++) {
final int index = i;
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat(
"HH:mm:ss");
System.out.println("運行時間: " +
sdf.format(new Date()) + " " + index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
cachedThreadPool.shutdown();
}
}
複製代碼
由於這種線程有新的任務提交,就會建立新的線程(線程池中沒有空閒線程時),不須要等待,因此提交的5個任務的運行時間是同樣的,運行結果以下:spa
運行時間: 08:45:18 2
運行時間: 08:45:18 1
運行時間: 08:45:18 3
運行時間: 08:45:18 4
運行時間: 08:45:18 0
複製代碼
首先,看一下這種線程池的建立方法:操作系統
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
複製代碼
從構造方法能夠看出,它建立了一個單線程化的線程池,它只會用惟一的工做線程來執行任務,保證全部任務按照指定順序執行。 那麼,如何使用newSingleThreadExecutor呢?咱們來舉個例子:線程
public class OneMoreStudy {
public static void main(String[] args) {
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 5; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
try {
SimpleDateFormat sdf = new SimpleDateFormat(
"HH:mm:ss");
System.out.println("運行時間: " +
sdf.format(new Date()) + " " + index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
singleThreadExecutor.shutdown();
}
}
複製代碼
由於該線程池相似於單線程執行,因此先執行完前一個任務後,再順序執行下一個任務, 運行結果以下:code
運行時間: 08:54:17 0
運行時間: 08:54:19 1
運行時間: 08:54:21 2
運行時間: 08:54:23 3
運行時間: 08:54:25 4
複製代碼
有的同窗可能會質疑:既然相似於單線程執行,那麼這種線程池還有存在的必要嗎?這裏的單線程執行指的是線程池內部,從線程池外的角度看,主線程在提交任務到線程池時並無阻塞,仍然是異步的。orm
這個方法建立了一個固定大小的線程池,支持定時及週期性任務執行。 首先看一下定時執行的例子:
public class OneMoreStudy {
public static void main(String[] args) {
final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
System.out.println("提交時間: " + sdf.format(new Date()));
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("運行時間: " + sdf.format(new Date()));
}
}, 3, TimeUnit.SECONDS);
scheduledThreadPool.shutdown();
}
}
複製代碼
使用該線程池的schedule方法,延遲3秒鐘後執行任務,運行結果以下:
提交時間: 09:11:39
運行時間: 09:11:42
複製代碼
再看一下週期執行的例子:
public class OneMoreStudy {
public static void main(String[] args) {
final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
System.out.println("提交時間: " + sdf.format(new Date()));
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("運行時間: " + sdf.format(new Date()));
}
}, 1, 3, TimeUnit.SECONDS);
Thread.sleep(10000);
scheduledThreadPool.shutdown();
}
}
複製代碼
使用該線程池的scheduleAtFixedRate方法,延遲1秒鐘後每隔3秒執行一次任務,運行結果以下:
提交時間: 09:23:20
運行時間: 09:23:21
運行時間: 09:23:24
運行時間: 09:23:27
複製代碼