一: newSingleThreadExecutor
創建一個單線程的線程池,以無界隊列方式運行。這個線程池只有一個線程在工作(如果這個唯一的線程因為異常結束,那么會有一個新的線程來替代它。)此線程池能夠保證所有任務的執行順序按照任務的提交順序執行,同一時段只有一個任務在運行。
此類型線程池特別適合於需要保證執行順序的場合。
package com.clzhang.sample.thread; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class ThreadPoolTest1 { static class MyThread implements Runnable { private String name; public MyThread(String name){ this.name = name; }
@Override public void run() { for (int i = 0; i < 2; i++) { // 做點事情 try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } // 如果用Thread.currentThread().getName()方法獲取當前線程名稱,則不會得到你想到的結果。 System.out.println(name + " said:" + i); } } }
public static void main(String[] args) { // 創建線程池 ExecutorService threadPool = Executors.newSingleThreadExecutor(); // ExecutorService threadPool = Executors.newFixedThreadPool(2); // ExecutorService threadPool = Executors.newCachedThreadPool();
// 向線程池里面扔任務 for (int i = 0; i < 4; i++) { threadPool.execute(new MyThread("Thread" + i)); }
// 關閉線程池 threadPool.shutdown(); } }
void execute(Runnable command):
在未來某個時間執行給定命令。該命令可能在新的線程、已入池的線程或者正調用的線程中執行,這由Executor決定。
void shutdown():
啟動一次順序關閉,執行以前提交的任務,但不接受新任務。如果已經關閉,則調用沒有其它作用。
輸出:
Thread0 said:0
Thread0 said:1
Thread1 said:0
Thread1 said:1
Thread2 said:0
Thread2 said:1
Thread3 said:0
Thread3 said:1
二:newFixedThreadPool
創建固定大小的線程池,以無界隊列方式運行。線程池滿且線程都為活動狀態的時候如果有新任務提交進來,它們會等待直到有線程可用。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那么線程池會補充一個新線程。顯式調用shutdown將關閉線程池。
此類型線程池比較符合常用場合。
更改注釋以使得上面的示范代碼中下述這代碼可用:
ExecutorService threadPool = Executors.newFixedThreadPool(2);
輸出:
Thread0 said:0
Thread1 said:0
Thread0 said:1
Thread1 said:1
Thread2 said:0
Thread3 said:0
Thread3 said:1
Thread2 said:1
三:newCachedThreadPool
創建一個可緩存的線程池。必要的時候創建新線程來處理請求,也會重用線程池中已經處於可用狀態的線程。如果線程池的大小超過了處理任務所需要的線程,那么就會回收部分空閑(60秒不執行任務)的線程;當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴於操作系統(或者說JVM)能夠創建的最大線程大小。
此類型線程池特別適合於耗時短,不需要考慮同步的場合。
更改注釋以使得上面的示范代碼中下述這代碼可用:
ExecutorService threadPool = Executors.newCachedThreadPool();
輸出:
Thread0 said:0
Thread2 said:0
Thread3 said:0
Thread1 said:0
Thread0 said:1
Thread2 said:1
Thread3 said:1
Thread1 said:1
四:newScheduledThreadPool
創建可定時運行(初始延時),運行頻率(每隔多長時間運行,還是運行成功一次之后再隔多長時間再運行)的線程池。
此類型線程池適合定時以及周期性執行任務的場合。
package com.clzhang.sample.thread; import java.util.*; import java.text.SimpleDateFormat; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class ThreadPoolTest2 { // 格式化時間 private static SimpleDateFormat MY_SDF = new SimpleDateFormat("mm:ss"); static class MyThread implements Runnable { @Override public void run() { // 做點事情 try { Thread.sleep(1000); System.out.println("[" + MY_SDF.format(new Date()) + "]finished job!"); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { // 創建線程池 ScheduledExecutorService schedulePool = Executors.newScheduledThreadPool(1); System.out.println("[" + MY_SDF.format(new Date()) + "]starting...");
// 初始延遲2秒后,只運行一次 schedulePool.schedule(new MyThread(), 2, TimeUnit.SECONDS); // 只運行一次,可以關閉池;下面的兩種方式(scheduleAtFixedRate/scheduleWithFixedDelay)則不可以關閉線程池! schedulePool.shutdown();
// 初始延遲2秒后,每間隔3秒運行一次線程 // schedulePool.scheduleAtFixedRate(new MyThread(), 2, 3, TimeUnit.SECONDS); // 初始延遲2秒后,每運行成功后再等3秒運行一次線程 // schedulePool.scheduleWithFixedDelay(new MyThread(), 2, 3, TimeUnit.SECONDS); } }
三個片段分別運行后的輸出:
[04:48]starting...
[04:51]finished job! // 延時2秒后啟動線程
-------------------------------------
[06:14]starting...
[06:17]finished job! // 初始延時2秒后啟動線程
[06:20]finished job! // 每隔3秒運行一次線程
[06:23]finished job!
......
-------------------------------------
[06:56]starting...
[06:59]finished job! // 初始延時2秒后啟動線程
[07:03]finished job! // 上次線程運行成功后再等3秒再次啟動
[07:07]finished job!
......