在Java中能夠經過線程池來達到線程複用的目的。在線程池中,線程已經預先被建立好,當線程執行完一個任務後,並不當即被銷燬,而是回到線程池中,繼續執行其它任務。這樣能夠提高系統的執行效率,由於建立和銷燬線程都須要時間。java
java.uitl.concurrent包是Java多線程併發工具包,此包下面有不少關於線程池的工具類。緩存
(1)Executor:一個接口,其定義了一個接收Runnable對象的方法executor,其方法簽名爲executor(Runnable command)。多線程
(2)ExecutorService:ExecutorService繼承了Executor。是一個比Executor使用更普遍的子類接口,其提供了生命週期管理的方法,以及可跟蹤一個或多個異步任務執行情況返回Future的方法。併發
(3)AbstractExecutorService:AbstractExecutorService實現了ExecutorService接口。異步
(4)ScheduledExecutorService:與AbstractExecutorService同樣實現了ExecutorService接口。它是一個可定時調度任務的接口。ide
(5)ScheduledThreadPoolExecutor:ScheduledExecutorService的實現,一個可定時調度任務的線程池。工具
(6)ThreadPoolExecutor:線程池,繼承了AbstractExecutorService。能夠經過調用Executors如下靜態工廠方法來建立線程池並返回一個ExecutorService對象。oop
(7)Executors:Executors 類提供工廠和使用方法用來建立不一樣類型的線程池。ui
public class ThreadPoolExecutor extends AbstractExecutorService { public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler); public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler); }
下面解釋下一下構造器中各個參數的含義:spa
(1)corePoolSize:核心池的大小,這個參數跟後面講述的線程池的實現原理有很是大的關係。在建立了線程池後,默認狀況下,線程池中並無任何線程,而是等待有任務到來才建立線程去執行任務,除非調用了prestartAllCoreThreads()或者prestartCoreThread()方法,從這2個方法的名字就能夠看出,是預建立線程的意思,即在沒有任務到來以前就建立corePoolSize個線程或者一個線程。默認狀況下,在建立了線程池後,線程池中的線程數爲0,當有任務來以後,就會建立一個線程去執行任務,當線程池中的線程數目達到corePoolSize後,就會把到達的任務放到緩存隊列當中;
(2)maximumPoolSize:線程池最大線程數,這個參數也是一個很是重要的參數,它表示在線程池中最多能建立多少個線程;
(3)keepAliveTime:表示線程沒有任務執行時最多保持多久時間會終止。默認狀況下,只有當線程池中的線程數大於corePoolSize時,keepAliveTime纔會起做用,直到線程池中的線程數不大於corePoolSize,即當線程池中的線程數大於corePoolSize時,若是一個線程空閒的時間達到keepAliveTime,則會終止,直到線程池中的線程數不超過corePoolSize。可是若是調用了allowCoreThreadTimeOut(boolean)方法,在線程池中的線程數不大於corePoolSize時,keepAliveTime參數也會起做用,直到線程池中的線程數爲0;
(3)unit:參數keepAliveTime的時間單位;
(4)workQueue:一個阻塞隊列,用來存儲等待執行的任務,這個參數的選擇也很重要,會對線程池的運行過程產生重大影響,通常來講,這裏的阻塞隊列有如下幾種選擇:ArrayBlockingQueue、LinkedBlockingQueue和SynchronousQueue。 ArrayBlockingQueue和PriorityBlockingQueue使用較少,通常使用LinkedBlockingQueue和Synchronous。線程池的排隊策略與BlockingQueue有關。
(5)threadFactory:線程工廠,主要用來建立線程;
(6)handler:表示當拒絕處理任務時的策略,有如下四種取值:
public class Executors { // 建立固定線程數目的線程池 public static ExecutorService newFixedThreadPool(int nThreads) {}; // 建立固定線程數目的線程池 public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {}; // 建立單一線程數目的線程池 public static ExecutorService newSingleThreadExecutor() {}; // 建立單一線程數目的線程池 public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {}; // 建立緩存線程數目的線程池 public static ExecutorService newCachedThreadPool() {}; // 建立緩存線程數目的線程池 public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {}; /** Cannot instantiate. */ private Executors() {} }
下面解釋下一下構造器中各個參數的含義:
(1)nThreads:建立線程的數目;
(2)threadFactory:工廠新建時使用的線程工廠;
(1)線程池:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * 線程池的使用實例 * * @author xiao */ public class ThreadPoolTest { public static void main(String[] args) { // ExecutorService threadPool = Executors.newFixedThreadPool(3); // 建立固定大小的線程池:起3個線程的線程池(固定線程數的線程池) // ExecutorService threadPool = Executors.newCachedThreadPool(); // 建立緩存線程池:線程池的線程數目隨實際運行線程的數目變化而變化 ExecutorService threadPool = Executors.newSingleThreadExecutor(); // 建立單一線程池:線程池中只有一個線程 for (int i = 0; i < 10; i++) { final int task = i; // 須要將task變量設置爲final,這樣在線程的runnable中才能訪問 threadPool.execute(new Runnable() { // 每一個runnable表示一個任務 @Override public void run() { for (int i = 1; i <= 10; i++) { // 此循環中的i和上面循環的i並非同一個方法中的變量,因此不會衝突 System.out.println(Thread.currentThread().getName() + " is loop of " + i + " task for " + task); } } }); } System.out.println("10 tasks have committed! "); threadPool.shutdown();// 線程池中無線程運行時,則關閉線程池 /** * 用線程池啓動定時器:調用 ScheduledExecutorServiced的schedule方法, * 返回的ScheduledFuture對象能夠取消任務支持間隔重複任務的定時方式, * 不直接支持絕對定時方式,須要轉換成相對時間方式 */ Executors.newScheduledThreadPool(3).scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("線程池定時器"); } }, 6, 1, TimeUnit.SECONDS); } }