1. 程式人生 > >JAVA多執行緒之執行緒池

JAVA多執行緒之執行緒池

一、執行緒池的概念

執行緒池(Thread Pool)對於限制應用程式中同一時刻執行的執行緒數很有用。因為每啟動一個新執行緒都會有相應的效能開銷,每個執行緒都需要給棧分配一些記憶體等等。

我們可以把併發執行的任務傳遞給一個執行緒池,來替代為每個併發執行的任務都啟動一個新的執行緒。只要池裡有空閒的執行緒,任務就會分配給一個執行緒執行。線上程池的內部,任務被插入一個阻塞佇列(Blocking Queue ),執行緒池裡的執行緒會去取這個佇列裡的任務。當一個新任務插入佇列時,一個空閒執行緒就會成功的從佇列中取出任務並且執行它。

具體說來,執行緒池的出現正是著眼於減少執行緒池本身帶來的開銷。執行緒池採用預建立的技術,在應用程式啟動之後,將立即建立一定數量的執行緒(N1),放入空閒佇列中。這些執行緒都是處於阻塞(Suspended)狀態,不消耗CPU,但佔用較小的記憶體空間。當任務到來後,緩衝池選擇一個空閒執行緒,把任務傳入此執行緒中執行。當N1個執行緒都在處理任務後,緩衝池自動建立一定數量的新執行緒,用於處理更多的任務。在任務執行完畢後執行緒也不退出,而是繼續保持在池中等待下一次的任務。當系統比較空閒時,大部分執行緒都一直處於暫停狀態,執行緒池自動銷燬一部分執行緒,回收系統資源。除此之外,執行緒池能夠減少建立的執行緒個數。通常執行緒池所允許的併發執行緒是有上界的,如果同時需要併發的執行緒數超過上界,那麼一部分執行緒將會等待。

Java 5 在 java.util.concurrent 包中自帶了內建的執行緒池,這裡我們只簡述一下相關介面和類的使用。

二、常用類和介面


Executor介面:這個介面只包括一個execute方法,是具體Runnable執行緒任務的執行者

ExecutorService介面

public interface ExecutorService extends Executor 

該介面是一個執行緒池管理者,繼承了Executor類。

這個介面還具有執行Callable任務的能力,通過submit()執行,關於使用Callable和Future開啟多執行緒的方法請參考文章   Java多執行緒:Callable、Future和FutureTask

。該介面的實現類有ThreadPoolExecutor、ScheduledThreadPoolExecutor(具有排程功能)

AbstractExecutorService:ExecutorService執行方法的預設實現
ScheduledExecutorService:一個可定時排程任務的介面 ScheduledThreadPoolExecutor:ScheduledExecutorService的實現,一個可定時排程任務的執行緒池
 
ThreadPoolExecutor:執行緒池,可以通過呼叫Executors以下靜態工廠方法來建立執行緒池並返回一個ExecutorService物件:

關於這個類的一個典型的構造方法如下:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

自定義執行緒池可以設定核心執行緒數、最大執行緒數、等待佇列等資訊。具體的引數設定不敢妄言,請查閱相關文件

ThreadPoolExecutor具有諸如啟動一個執行緒、返回執行緒池配置、修改當前執行緒池配置等方法。

下面的例子,給了一個自定義執行緒池,並返回了執行緒池的資訊

    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
        CallTask task = new CallTask();
        for (int i = 0; i < 5; i++) {
            threadPoolExecutor.submit(task);
        }
        threadPoolExecutor.setCorePoolSize(10);				            //修改執行緒池的核心執行緒數
        System.out.println(threadPoolExecutor.getThreadFactory());	    //返回執行緒工廠
        System.out.println(threadPoolExecutor.getCorePoolSize());	    //得到當前執行緒池的核心執行緒數
        System.out.println(threadPoolExecutor.getPoolSize());		    //得到池中的當前執行緒數
        System.out.println(threadPoolExecutor.getMaximumPoolSize());    //得到允許的最大執行緒數
        System.out.println(threadPoolExecutor.getQueue());		        //返回執行程式使用的任務佇列
    }
輸出結果
[email protected]
10
5
2147483647
[]

Executors類

提供了一系列靜態工廠方法用於建立各種執行緒池,分別是:

newCachedThreadPool //建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。
newFixedThreadPool  //建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
newScheduledThreadPool  //建立一個定長執行緒池,支援定時及週期性任務執行。
newSingleThreadExecutor  //建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。