JDK文檔說明:
創建一個可重用固定線程數的線程池,以共享的無界隊列方式來運行這些線程。在任意點,在大多數 nThreads 線程會處於處理任務的活動狀態。如果在所有線程處於活動狀態時提交附加任務,則在有可用線程之前,附加任務將在隊列中等待。如果在關閉前的執行期間由於失敗而導致任何線程終止,那么一個新線程將代替它執行后續的任務(如果需要)。在某個線程被顯式地關閉之前,池中的線程將一直存在。
創建方法:
java.util.concurrent.Executors.newFixedThreadPool(int nThreads) or java.util.concurrent.Executors.newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
調用上面2個方法得到的對象為:ExecutorService
JDK自帶的例子:
下面給出了一個網絡服務的簡單結構,這里線程池中的線程作為傳入的請求。它使用了預先配置的 Executors.newFixedThreadPool(int)
工廠方法:
class NetworkService implements Runnable { private final ServerSocket serverSocket; private final ExecutorService pool; public NetworkService(int port, int poolSize) throws IOException { serverSocket = new ServerSocket(port); pool = Executors.newFixedThreadPool(poolSize); } public void run() { // run the service try { for (;;) { pool.execute(new Handler(serverSocket.accept())); } } catch (IOException ex) { pool.shutdown(); } } } class Handler implements Runnable { private final Socket socket; Handler(Socket socket) { this.socket = socket; } public void run() { // read and service request on socket } }
主要的方法:
boolean |
|
|
<T> List<Future<T>> |
invokeAll(Collection<? extends Callable<T>> tasks) 執行給定的任務,當所有任務完成時,返回保持任務狀態和結果的 Future 列表。 |
|
|
invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) 執行給定的任務,當所有任務完成或超時期滿時(無論哪個首先發生),返回保持任務狀態和結果的 Future 列表。 |
|
|
invokeAny(Collection<? extends Callable<T>> tasks) 執行給定的任務,如果某個任務已成功完成(也就是未拋出異常),則返回其結果。 |
|
|
invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) 執行給定的任務,如果在給定的超時期滿前某個任務已成功完成(也就是未拋出異常),則返回其結果。 |
|
boolean |
isShutdown() 如果此執行程序已關閉,則返回 true。 |
|
boolean |
isTerminated() 如果關閉后所有任務都已完成,則返回 true。 |
|
void |
shutdown() 啟動一次順序關閉,執行以前提交的任務,但不接受新任務。 |
|
List<Runnable> |
shutdownNow() 試圖停止所有正在執行的活動任務,暫停處理正在等待的任務,並返回等待執行的任務列表。 |
|
|
submit(Callable<T> task) 提交一個返回值的任務用於執行,返回一個表示任務的未決結果的 Future。 |
|
Future<?> |
submit(Runnable task) 提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。 |
|
|
|
|
void |
|
自己寫的例子:
package com.yzl; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; public class ThreadPool { public static void main(String[] args) { fixedThreadPool(); } /** * 固定大小的線程池 * * 同時可以處理【參數】個任務,多余的任務會排隊,當處理完一個馬上就會去接着處理排隊中的任務。 * Callable的任務在后面的blog有更詳細的文章說明 */ private static void fixedThreadPool(){ ExecutorService es = Executors.newFixedThreadPool(2); //加入5個任務 for(int i=1 ; i<5; i++){ final int task = i; es.execute(new Runnable() { @Override public void run() { for(int j=1; j<=2; j++){ System.out.println("現在運行的是第【 " + task + "】任務"); System.out.println(Thread.currentThread().getName() + "is work , now loop to " + j); if(j==2){ System.out.println("任務 【" + task + "】運行完成"); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }); } System.out.println("5個Runnable任務submit完成!!"); //加入5個Callable任務,該任務執行完后是有返回值的則會發生堵塞,也就是取到5個任務的結果后才會繼續往下走 for(int i=1 ; i<=5; i++){ final int task = i; Future<Integer> future = es.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Callable 任務【" + task + "】運行"); return new Random().nextInt(100); } }); //如果注釋取結果的代碼,則不會堵塞 /*try { System.out.println("任務【" + i + "】返回的結果:" + future.get()); } catch (Exception e) { e.printStackTrace(); }*/ } System.out.println("5個Callable任務submit完成!!" + System.currentTimeMillis() ); //雖然shutdown方法是等所有任務跑完后才真正停掉線程池,但該方法不會造成堵塞,也就是這代碼運行后,下一行代碼會立刻運行 es.shutdown(); System.out.println("主程序shutdown后退出!!" + System.currentTimeMillis()); //暴力的直接終止線程池 //es.shutdownNow(); //awaitTermination方法是堵塞式的,只有等真的把線程池停掉才會讓程序繼續往下執行 try { es.awaitTermination(2, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("主程序后awaitTermination退出!!" + System.currentTimeMillis()); } }