java並發編程--Executor架構

來源:互聯網
上載者:User

標籤:關閉   single   mil   監視   阻塞隊列   重複   阻塞   dfa   service   

摘要:

       Eexecutor作為靈活且強大的非同步執行架構,其支援多種不同類型的任務執行策略,提供了一種標準的方法將任務的提交過程和執行過程解耦開發,基於生產者-消費者模式,其提交任務的線程相當於生產者,執行任務的線程相當於消費者,並用Runnable來表示任務,Executor的實現還提供了對生命週期的支援,以及統計資訊收集,應用程式管理機制和效能監控等機制。 1.Exexctor簡介Executor的UML圖:(常用的幾個介面和子類)Executor:一個介面,其定義了一個接收Runnable對象的方法executor,其方法簽名為executor(Runnable command), ExecutorService:是一個比Executor使用更廣泛的子類介面,其提供了生命週期管理的方法,以及可跟蹤一個或多個非同步任務執行狀況返回Future的方法 AbstractExecutorService:ExecutorService執行方法的預設實現 ScheduledExecutorService:一個可定時調度任務的介面 ScheduledThreadPoolExecutor:ScheduledExecutorService的實現,一個可定時調度任務的線程池 ThreadPoolExecutor:線程池,可以通過調用Executors以下靜態Factory 方法來建立線程池並返回一個ExecutorService對象: 2.ThreadPoolExecutor建構函式的各個參數說明ThreadPoolExecutor方法簽名:
public ThreadPoolExecutor(int corePoolSize,                          int maximumPoolSize,                          long keepAliveTime,                          TimeUnit unit,                          BlockingQueue<Runnable> workQueue,                          ThreadFactory threadFactory,                          RejectedExecutionHandler handler) //後兩個參數為選擇性參數
參數說明:corePoolSize:核心線程數,如果啟動並執行線程少於corePoolSize,則建立新線程來執行新任務,即使線程池中的其他線程是閒置 maximumPoolSize:最大線程數,可允許建立的線程數,corePoolSize和maximumPoolSize設定的邊界自動調整池大小:corePoolSize <啟動並執行線程數< maximumPoolSize:僅當隊列滿時才建立新線程corePoolSize=啟動並執行線程數= maximumPoolSize:建立固定大小的線程池 keepAliveTime:如果線程數多於corePoolSize,則這些多餘的線程的空閑時間超過keepAliveTime時將被終止 unit:keepAliveTime參數的時間單位 workQueue:儲存任務的阻塞隊列,與線程池的大小有關:  當啟動並執行線程數少於corePoolSize時,在有新任務時直接建立新線程來執行任務而無需再進隊列  當啟動並執行線程數等於或多於corePoolSize,在有新任務添加時則選排入佇列,不直接建立線程  當隊列滿時,在有新任務時就建立新線程 threadFactory:使用ThreadFactory建立新線程,預設使用defaultThreadFactory建立線程 handle:定義處理被拒絕任務的策略,預設使用ThreadPoolExecutor.AbortPolicy,任務被拒絕時將拋出RejectExecutorException 3.Executors:提供了一系列靜態Factory 方法用於建立各種線程池   newFixedThreadPool:建立可重用且固定線程數的線程池,如果線程池中的所有線程都處於活動狀態,此時再提交任務就在隊列中等待,直到有可用線程;如果線程池中的某個線程由於異常而結束時,線程池就會再補充一條新線程。方法簽名:
public static ExecutorService newFixedThreadPool(int nThreads) {    return new ThreadPoolExecutor(nThreads, nThreads,                                  0L, TimeUnit.MILLISECONDS,                                  //使用一個基於FIFO排序的阻塞隊列,在所有corePoolSize線程都忙時新任務將在隊列中等待                                  new LinkedBlockingQueue<Runnable>());}

newSingleThreadExecutor:建立一個單線程的Executor,如果該線程因為異常而結束就建立一條線程來繼續執行後續的任務

方法簽名:
public static ExecutorService newSingleThreadExecutor() {   return new FinalizableDelegatedExecutorService                     //corePoolSize和maximumPoolSize都等於,表示固定線程池大小為1                        (new ThreadPoolExecutor(1, 1,                                                0L, TimeUnit.MILLISECONDS,                                                new LinkedBlockingQueue<Runnable>()));}

newScheduledThreadPool:建立一個可順延強制或定期執行的線程池

方法簽名:

例1:(使用newScheduledThreadPool來類比心跳機制)

public class HeartBeat {    public static void main(String[] args) {        ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);        Runnable task = new Runnable() {            public void run() {                System.out.println("HeartBeat.........................");            }        };        executor.scheduleAtFixedRate(task,5,3, TimeUnit.SECONDS);   //5秒後第一次執行,之後每隔3秒執行一次    }}

輸出:

HeartBeat....................... //5秒後第一次輸出........ //每隔3秒輸出一個

newCachedThreadPool:建立可快取的線程池,如果線程池中的線程在60秒未被使用就將被移除,在執行新的任務時,當線程池中有之前建立的可用線程就重      用可用線程,否則就建立一條線程

方法簽名:
public static ExecutorService newCachedThreadPool() {    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,                                  60L, TimeUnit.SECONDS,                                  //使用同步隊列,將任務直接提交給線程                                  new SynchronousQueue<Runnable>());}

例2

public class ThreadPoolTest {    public static void main(String[] args) throws InterruptedException {     ExecutorService threadPool = Executors.newCachedThreadPool();//線程池裡面的線程數會動態變化,並可線上程線被移除前重用        for (int i = 1; i <= 3; i ++) {            final  int task = i;   //10個任務            //TimeUnit.SECONDS.sleep(1);            threadPool.execute(new Runnable() {    //接受一個Runnable執行個體                public void run() {                        System.out.println("線程名字: " + Thread.currentThread().getName() +  "  任務名為: "+task);                }            });        }    }}

輸出:(為每個任務建立一條線程,共建立了3條線程)

線程名字: pool-1-thread-1 任務名為: 1線程名字: pool-1-thread-2 任務名為: 2線程名字: pool-1-thread-3 任務名為: 3

去掉第6行的注釋其輸出如下:(始終重複利用一條線程,因為newCachedThreadPool能重用可用線程)

線程名字: pool-1-thread-1 任務名為: 1線程名字: pool-1-thread-1 任務名為: 2線程名字: pool-1-thread-1 任務名為: 3

通過使用Executor可以很輕易的實現各種調優  管理  監視  記錄日誌和錯誤報表等待。

 4.Executor的生命週期ExecutorService提供了管理Eecutor生命週期的方法,ExecutorService的生命週期包括了:運行  關閉和終止三種狀態。 ExecutorService在初始化建立時處於運行狀態。shutdown方法等待提交的任務執行完成並不再接受新任務,在完成全部提交的任務後關閉shutdownNow方法將強制終止所有運行中的任務並不再允許提交新任務 可以將一個Runnable(如例2)或Callable(如例3)提交給ExecutorService的submit方法執行,最終返回一上Future用來獲得任務的執行結果或取消任務例3:(任務執行完成後並返回執行結果)
public class CallableAndFuture {    public static void main(String[] args) throws ExecutionException, InterruptedException {        ExecutorService executor = Executors.newSingleThreadExecutor();        Future<String> future = executor.submit(new Callable<String>() {   //接受一上callable執行個體            public String call() throws Exception {                return "MOBIN";            }        });        System.out.println("任務的執行結果:"+future.get());    }}

輸出:

任務的執行結果:MOBIN

ExecutorCompletionService:實現了CompletionService,將執行完成的任務放到阻塞隊列中,通過take或poll方法來獲得執行結果

例4:(啟動10條線程,誰先執行完成就返回誰) 
public class CompletionServiceTest {    public static void main(String[] args) throws InterruptedException, ExecutionException {        ExecutorService executor = Executors.newFixedThreadPool(10);        //建立含10.條線程的線程池        CompletionService completionService = new ExecutorCompletionService(executor);        for (int i =1; i <=10; i ++) {            final  int result = i;            completionService.submit(new Callable() {                public Object call() throws Exception {                    Thread.sleep(new Random().nextInt(5000));   //讓當前線程隨機休眠一段時間                    return result;                }            });        }        System.out.println(completionService.take().get());   //擷取執行結果    }}

輸出結果可能每次都不同(在1到10之間)

3

通過Executor來設計應用程式可以簡化開發過程,提高開發效率,並有助於實現並發,在開發中如果需要建立線程可優先考慮使用Executor

java並發編程--Executor架構

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.