1. 程式人生 > >我與狗子的日常5

我與狗子的日常5

執行緒池淺析

執行緒池顧名思義就是放執行緒的池子 Thread Pool。

那麼為什麼要有執行緒池呢?有些時候系統需要處理非常多的執行時間很短的請求,如果每一個請求都開啟一個新的執行緒,則系統建立銷燬執行緒的開銷就太大了,甚至在建立和銷燬執行緒的時間比任務的執行時間還長。

使用new Thread() 會有如下缺點:

1.建立和銷燬執行緒耗費大量系統資源;

2.每次new Thread() 缺乏執行緒管理,被稱為野執行緒,而且可以無限制建立,之間相互競爭,會導致過多佔用系統資源導致系統癱瘓。

3.不利於擴充套件,如定期執行,定時執行,執行緒中斷。

執行緒池主要解決了兩個問題:

       1.通過重用執行緒,達到減少每個執行緒建立和銷燬的效能開銷。

       2.對執行緒進行一些維護,比如定時開始,週期執行,併發控制等。

       3.可控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭。

Executor:JDK1.5引入,內部使用執行緒池機制,在java.util.cocurrent包下,Executor框架包括:執行緒池,Executor,Executors,ExecutorService,CompletionService,Future,Callable,ThreadPoolExecutor等。

Executors:工廠類 建立執行緒池

1.newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {

    return new ThreadPoolExecutor(nThreads, nThreads,

                                  0L, TimeUnit.MILLISECONDS,

                                  new LinkedBlockingQueue<Runnable>());

}

 

建立一個固定數目的執行緒池,內部維持一個無界的佇列,當所有的執行緒都在處於活動狀態時提交了其他任務,則新任務將在佇列中等待直到執行緒可用。

2.newCachedThreadPool
public static ExecutorService newCachedThreadPool() 
{

    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

                                  60L, TimeUnit.SECONDS,

                                  new SynchronousQueue<Runnable>());

}

 

建立一個根據需要建立新執行緒的執行緒池,但在可用時將重新使用以前構造的執行緒。

該執行緒池適用於執行許多短暫非同步任務的程式,呼叫execute會重用以前構造的執行緒,如果沒有可用的執行緒,則會建立新的執行緒,並將該執行緒新增到該池中,未使用60秒的執行緒將被終止並從快取中刪除。因此,長時間保持閒置的池將不會消耗任何資源。

3.newSingleThreadExecutor
public static ExecutorService newSingleThreadExecutor() {

    return new FinalizableDelegatedExecutorService

        (new ThreadPoolExecutor(1, 1,

                                0L, TimeUnit.MILLISECONDS,

                                new LinkedBlockingQueue<Runnable>()));

}

 

建立一個使用無界佇列執行單個工作執行緒的執行程式,等效於newFixedThreadPool(1)

4.newScheduledThreadPool
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {

    return new ScheduledThreadPoolExecutor(corePoolSize);

}

 

建立一個執行緒池,可以排程命令在給定的延遲之後執行,或定期執行。

scheduleAtFixedRate(Runnable command,
                                                 long initialDelay,
                                                 long delay,
                                                 TimeUnit unit);

首次執行在 initialDelay 之後,第二次 執行時間為 initialDelay+delay*1 ….

scheduleWithFixedDelay(Runnable command,
                                                 long initialDelay,
                                                 long delay,
                                                 TimeUnit unit);

第一次的執行時間為 當前時間+ initialDelay,第二次為第一次執行結束時間+delay

ExecutorService 的submit() 和 execute()區別:

1.入參不同 submit可以接收Runnable或者Callable ,execute方法只能接收Runnable

2.返回值 submit 有返回值 而 execute沒有返回值

3.submit方便處理Exception  Future.get丟擲的異常

Runnable和Callable的區別

Callable介面中的call方法是有返回值的,泛型可任意制定,但是Runnable介面中run方法是沒有返回值的。

ThreadPoolExecutor:JDK提供的Executors工具類中建立的執行緒無法滿足使用場景時,則需要手動配置和調優,則用到該池。

public ThreadPoolExecutor(int corePoolSize,

                          int maximumPoolSize,

                          long keepAliveTime,

                          TimeUnit unit,

                          BlockingQueue<Runnable> workQueue) {

    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

         Executors.defaultThreadFactory(), defaultHandler);

}

引數詳解:

corePoolSize:核心執行緒數

maximumPoolSize:最大執行緒數

keepAliveTime:最大空閒時間

BlockingQueue:使用的任務佇列

               ArrayBlockingQueue:底層是陣列的定長任務佇列,必須制定長度,可設定是               否公平鎖。預設先進先出

               LinkedBlockingQueue:底層為連結串列的可定長任務佇列,不指定長度則為無界,             可設定公平鎖,預設為先進先出

               SynchronousQueue:同步的沒有緩衝的任務佇列,只有當執行緒將佇列中的take走之後,才能新加進來任務

defaultHandler:該引數代表的是拒絕策略,預設為AbortPolicy

可以通過設定改變

/**
 * ThreadPoolExecutor.AbortPolicy() 
丟擲java.util.concurrent.RejectedExecutionException異常
 
* ThreadPoolExecutor.CallerRunsPolicy() 使用主執行緒跑當前任務
 
* ThreadPoolExecutor.DiscardOldestPolicy() 拋棄舊的任務
 
* ThreadPoolExecutor.DiscardPolicy() 拋棄當前的任務
 
*/