java封裝的幾個線程池介紹__java

來源:互聯網
上載者:User
java封裝的幾個線程池介紹 FixedThreadPool

FixedThreadPool並不是一個類,它是由Executors工具類建立出來的一個固定線程數的一個ThreadPoolEexcutor的對象,有2種實現方式。

Executors.newFixedThreadPool(3);//固定3個線程數Executors.newFixedThreadPool(3, Executors.defaultThreadFactory());

我們來看下newFixedThreadPool()的內部實現吧

public static ExecutorService newFixedThreadPool(int nThreads) {    //這裡可以看出,返回的就是一個TreadPoolExecutor對象,不過這個對象的核心線程數和最大線程數相等    return new ThreadPoolExecutor(nThreads, nThreads,                              0L, TimeUnit.MILLISECONDS,                              new LinkedBlockingQueue<Runnable>());}public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {    return new ThreadPoolExecutor(nThreads, nThreads,                                  0L, TimeUnit.MILLISECONDS,                                  new LinkedBlockingQueue<Runnable>(),                                  //相比上面的方法,就是多了threadFactory參數                                  threadFactory);}

newFixedThreadPool()分析

這裡就用一個參數的方法來分析。 corePoolSize和maxPoolSize都是參數nThreads:線程池中都是核心線程且是nThraeds個時,沒有非核心線程。 非背景工作執行緒的存活時間是0:當核心線程執行完隊列中的任務時,如果隊列中沒有任務,這時核心線程死亡。極大程度的節約了系統資源。 使用的隊列預設最大值是Integer.MAX_VALUE:該隊列長度是int最大值,相當於無限大了,這樣不管你有多少任務,都能夠儲存在隊列裡面,等待核心線程去執行。

線程池中執行任務大致分為4個階段

1.任務數小於核心線程數,如果在執行新任務,則建立核心線程去執行任務。

2.當核心線程都在執行任務時,未執行的任務且小於隊列長度,這是任務會儲存於隊列中。

3.當核心線程都在執行任務,且未執行任務數大於隊列長度,這是非核心線程會執行新的任務。

4.當核心線程都在執行任務,且未執行任務數大於隊列長度,且非核心線程也在執行任務,這是會採用飽和策略。

newFixedPoolExecutor()建立出來的線程池,不會有第3階段。

FixedPoolExecutor的使用情境

FixedThreadPool適用於為了滿足資源管理的需求,而需要限制當前線程數量的應用情境,它適用於負載比較重的伺服器。 SingleThreadPool

SingleThreadPool是只有一個線程的線程池,內部實現和FixedThreadPool一樣,不過就是線程數有區別。

SingleThreadPool的調用方法

Executors.newSingleThreadExecutor();Executors.newSingleThreadExecutor(Executors.defaultThreadFactory());

SingleThreadPool的內部實現

public static ExecutorService newSingleThreadExecutor() {    return new FinalizableDelegatedExecutorService(                            new ThreadPoolExecutor(1, 1,                                0L, TimeUnit.MILLISECONDS,                                new LinkedBlockingQueue<Runnable>()));}public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {    return new FinalizableDelegatedExecutorService        (new ThreadPoolExecutor(1, 1,                                0L, TimeUnit.MILLISECONDS,                                new LinkedBlockingQueue<Runnable>(),                                threadFactory));}

我們看到new FinalizableDelegatedExecutorService()對象包裹了一個ThreadPoolExecutor對象,這個ThreadPoolExecutor對象其實就是一個線程的FixedThreadPool,而FinalizableDelegatedExecutorService類就是對ThreadPoolExecutor在封裝了一層。

所以我們也可以簡單的理解為SingleThreadPool是只有一個線程的FixedThreadPool。 CachedThreadPool

CachedThreadPool的調用方法

Executors.newCachedThreadPool();Executors.newCachedThreadPool(Executors.defaultThreadFactory());

CachedThreadPool的內部實現

public static ExecutorService newCachedThreadPool() {    return new ThreadPoolExecutor(0,Integer.MAX_VALUE,                              60L, TimeUnit.SECONDS,                              new SynchronousQueue<Runnable>());}public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                  60L, TimeUnit.SECONDS,                                  new SynchronousQueue<Runnable>(),                                  threadFactory);}

newCachedThreadPool()中的ThreadPoolExecutor對象參數分析 corePoolSize核心線程數為0 maxPoolSize最大線程數為Integer.MAX_VALUE。 keepAliveTime:非背景工作執行緒存活時間60秒 workQueue:隊列使用的SynchronousQueue(SynchronousQueue是一個沒有容量的隊列)。

通過參數我們可以知道,沒有核心線程數,那麼就不會走線程池的第一個階段,SynchronousQueue隊列是一個沒有容量的阻塞隊列。每個插入操作必須等待另一 個線程的對應移除操作。

下面看下CachedThreadPool的execute()方法的執行示意圖:

1.execute()首先執行SynchronousQueue.offer(Runnable r)。如果的當前maxPool中有空閑線程,會執行SynchronousQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS),那麼主線程(調用execute()的線程)執行offer操作與空閑線程執行的poll操作配對成功。主線程把任務交給空閑線程執行,execute()方法執行完成。

2.當maxPool為空白,或者maxPool中當前沒有空閑線程時,將沒有線程執行SynchronousQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)。這種情況下,步驟1失敗。此時CachedThreadPool會建立一個新線程執行任務,execute()執行完成。

3.在步驟2中,新建立的線程將任務執行完後,會執行SynchronousQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)。這個poll操作會讓空閑線程最多在SynchronousQueue中等待60秒,如果60秒鐘內主線程提交了一個新任務(主線程執行步驟1),那麼這個空閑線程將執行主線程提交的新任務;否則,這個空閑線程將終止。由於空閑60秒的空閑線程會被終止,因此長時間保持閒置CachedThreadPool不會使用任何資源。

CachedThreadPool是大小無界的線程池,適用於執行很的短期非同步任務的小程式,或者是負載較輕的伺服器。 ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor是ThreadPoolExecutor的子類。

ScheduledThreadPoolEexcutor的調用有4中形式

Executors.newScheduledThreadPool(3);Executors.newScheduledThreadPool(3, Executors.defaultThreadFactory());new ScheduledThreadPoolExecutor(3);new ScheduledThreadPoolExecutor(3, Executors.defaultThreadFactory());

其實Executors.newScheduledThreadPool(3)方法的內部實現也是直接建立一個對象,如:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {    return new ScheduledThreadPoolExecutor(corePoolSize);}public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {    return new DelegatedScheduledExecutorService        (new ScheduledThreadPoolExecutor(1, threadFactory));}

那我們接下來看下ScheduledThreadPoolExecutor()的構造方法實現

public ScheduledThreadPoolExecutor(int corePoolSize) {    super(corePoolSize, Integer.MAX_VALUE,          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,          new DelayedWorkQueue());}public ScheduledThreadPoolExecutor(int corePoolSize,ThreadFactory threadFactory) {    super(corePoolSize, Integer.MAX_VALUE,          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,          new DelayedWorkQueue(), threadFactory);}

從構造方法中可以知道,其實ScheduledThreadPoolExecutor調用的是父類中的構造方法,也就是ThreadPoolExecutor中的構造。那麼我們來說說傳入的參數: corePoolSize:核心線程數,傳入 預設最大線程數為Integer.MAX_VALUE。 保活時間預設10毫秒,DEFAULT_KEEPALIVE_MILLIS預設10L,單位毫秒。 使用的隊列是DelayedWorkQueue,DelayedWorkQueue是一個無界限的隊列,當添加的任務大於隊列時,會從新增加隊列的長度。同時DelayedWorkQueue還有著一套按逾時時間升序排序的演算法,遵循”左結點比右節點小(下次執行的時間更短)的原則。具體細節在下一章解釋。

通過構造我們可以知道,ScheduledThreadPoolExecutor和ThreadPoolExecutor並沒太多的區別,最大的區別就是隊列的不同。因為DelayedWorkQueue的長度具有增長型和按逾時時間升序排序演算法,使得ScheduledThreadPoolExecutor具有延時執行任務的特性。

因為DelayedWorkQueue是屬於無界隊列,那麼最大線程數設定Integer.MAX_VALUE就沒有使用到。

ScheduledThreadPoolExecutor的執行方法

因為ScheduledThreadPoolExecutor繼承自ThreadPoolExecutor,所以會有execute()和submit(),這裡不介紹這2個方法。

ScheduledThreadPoolExecutor除了繼承ThreadPoolExecutor,還實現了ScheduledExecutorService介面

ScheduledExecutorService介面方法

//建立任務並在給定延遲時間後執行public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);//同上,只不過參數是Callablepublic <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);/** * 參數initialDelay:表示第一次延時的時間 * 參數period:表示任務執行開始後距下一個任務開始執行的時間間隔 */public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);/** * 參數initialDelay:表示第一次延時的時間 * 參數period:表示任務執行結束後距下一個任務開始執行的時間間隔 */                                 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);                                            

schedule()方法實現代碼:

public ScheduledFuture<?> schedule(Runnable command,long delay,TimeUnit unit) {    if (command == null || unit == null)        throw new NullPointerException();    //decorateTask()的第2個參數,就是傳回值,也就是即將順延強制的任務對象    RunnableScheduledFuture<Void> t = decorateTask(command,new ScheduledFutureTask<Void>(command, null,triggerTime(delay, unit),sequencer.getAndIncrement()));    delayedExecute(t);//順延強制這個任務    return t;}//decorateTask()實現代碼protected <V> RunnableScheduledFuture<V> decorateTask(Runnable runnable, RunnableScheduledFuture<V> task) {    return task;}

ScheduledThreadPoolExecutor的執行方法非常類似Timer定時器。

ScheduledThreadPoolExecutor的簡單使用 schedule()的使用

public class Test {    public static void main(String[] args) {        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(3);        System.out.println("任務執行前時間:" + System.currentTimeMillis());//任務執行前時間:1496847975977        scheduledThreadPoolExecutor.schedule(new Runnable() {            @Override            public void run() {                System.out.println("任務執行時間:" + System.currentTimeMillis());//任務執行時間:1496847976993            }        }, 1000, TimeUnit.MILLISECONDS);    }}
scheduleAtFixedRate()的使用
public class Test {    public static void main(String[] args) {        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(3);        System.out.println("任務執行前時間:" + System.currentTimeMillis());        scheduledThreadPoolExecutor.scheduleAtFixedRate(new Runnable() {            @Override            public void run() {                System.out.println("任務執行時間:" + System.currentTimeMillis());                try {                    Thread.sleep(1000);//這個是為了區別和下一個方法                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }, 1000, 5000, TimeUnit.MILLISECONDS);    }}控制台列印結果:任務執行前時間:1496848166272任務執行時間:1496848167285     //第一次執行,任務延遲1秒執行任務執行時間:1496848172281     //每隔5秒後執行任務任務執行時間:1496848177280任務執行時間:1496848182282任務執行時間:1496848187282
scheduleWithFixedDelay()的使用
public class Test {    public static void main(String[] args) {        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(3);        System.out.println("任務執行前時間:" + System.currentTimeMillis());//任務執行前時間:1496847975977        scheduledThreadPoolExecutor.scheduleWithFixedDelay(new Runnable() {            @Override            public void run() {                System.out.println("任務執行時間:" + System.currentTimeMillis());                try {                    Thread.sleep(1000);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }, 1000, 5000, TimeUnit.MILLISECONDS);    }}列印結果:任務執行前時間:1496848595162任務執行時間:1496848596181     //第一次執行延時任務,延遲1秒任務執行時間:1496848602188     //第2次執行任務,延遲大約6秒(5秒是延遲時間,1秒是任務執行的消耗時間)任務執行時間:1496848608204任務執行時間:1496848614211任務執行時間:1496848620231任務執行時間:1496848626256

ScheduledThreadPoolExecutor停止方法 shutdown() shutdownNow()

這兩個方法在將線程池ThreadPoolExecutor的時候介紹過。 SingleThreadScheduledExecutor

SingleThreadScheduledExecutor和ScheduledThreadPoolExecutor一樣具有延時執行任務的特點。SingleThreadScheduledExecutor的內部實現就是ScheduledThreadPoolExecutor,只不過只有一個核心線程(雖然有最大線程數,但是隊列的無邊界的,所以除核心線程外,其他線程不會執行任務)。

SingleThreadScheduledExecutor的調用

Executors.newSingleThreadScheduledExecutor();Executors.newSingleThreadScheduledExecutor(Executors.defaultThreadFactory());

SingleThreadScheduledExecutor的內部實現

public static ScheduledExecutorService newSingleThreadScheduledExecutor() {    return new DelegatedScheduledExecutorService        (new ScheduledThreadPoolExecutor(1));}public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {    return new DelegatedScheduledExecutorService        (new ScheduledThreadPoolExecutor(1, threadFactory));}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.