Java併發編程實戰筆記(5)-任務執行

轉載請註明出處 http://www.paraller.com
原文排版地址 點擊跳轉-任務執行/)緩存

相關知識點

  • 大多數併發應用,都是經過任務執行來構造的,經過將任務分紅小的工做單元,提供一種天然的事務邊界來優化錯誤恢復過程.
  • 任務執行(Task Execution)的重點在於:獨立性明確的任務執行策略
  • 無限制建立線程的不足併發

    • 線程的建立須要時間,消耗大量的運算資源
    • 活躍的線程消耗系統資源,特別是內存;可運行的線程數量多於CPU的數量將會形成閒置,佔用內存,大量線程還會引發競爭
    • 穩定性:JVM和Thread構造函數指定的棧大小,以及系統對線程的限制都會形成崩潰。
  • future能夠設置超時時間。

Note:
32位的機器,限制因素主要是線程棧的地址空間,每一個線程維護兩個執行棧,一個用於Java代碼,一個用於原生代碼,一般JVM會默認建立一個複合棧,大概是0.5兆(經過 -Xss或者Thread構造函數來設置),2的32次方除以棧大小,會將線程限制在幾萬內。異步

Executor

  • 任務是一組邏輯工做單元 , 而線程則是任務異步執行的機制
  • Executor能支持多種不一樣類型的任務執行策略
  • 提供了一種標準的方法將 任務的提交任務的執行 分開,使用Runnable表示任務
  • 提供了對生命週期統計信息收集程序管理性能監控的支持。
  • 基於生產者-消費者模式,提交任務是生產,執行任務的線程至關於消費者
  • 經過不一樣的 Executor的實現就能改變程序的行爲。
  • Java類庫中,任務執行的主要抽象不是 Thread,而是 Executor
interface Executor{
    void execute(Runnable command);
}
class Demo{
    private final Executor exec = Executors.newFixedThreadPool(100);
    
    void test(){
        // 運行
        Runnable task = new Runnable(){
            public void run(){
                //...
            }
        }
        // 提交
        exec.execute(task);
        
    }
}
線程池

經過管理一組工做線程的資源池,可以減小建立和銷燬的開銷(資源層面),而且不須要等待,提升響應性
Executor靜態工廠方法提供如下幾種資源池:函數

  • newFixedThreadPool: 固定大小,若是線程異常結束會補充
  • newCachedThreadPool: 可緩存線程池,少了建立,多了回收
  • newSingleThreadExecutor: 單線程,會按照隊列中的順序(可設置)串行執行
  • newScheduledThreadPool: 固定大小,能延遲或者定時執行
Executor生命週期

Executor實現一般建立線程執行,JVM只有在全部的非守護線程結束才能關閉,
類庫提供了 基於 Executor的 ExecutorService接口性能

  • shutdown: 不接受新任務,等待開始的任務結束
  • shutdownNow: 嘗試取消全部開始的任務,再也不啓動還沒有開始(多是已接受的新任務)執行的任務。
interface ExecutorService extends Executor{
    void shutdown();
    List<Runnable> shutdownNow();
    boolean isShutdown();
    ...//
}

生命週期三種狀態 運行、關閉、已終止優化

  • ExecutorService關閉後,提交新的任務會拋出 RejectExecutionException
  • 全部任務完成會變成已終止狀態
  • awaitTermination會等待 Executor到達終止狀態,而且會當即調用shutdown方法。
  • ExecutorService全部submit方法,都會返回一個Future
Timer和ScheduledThreadPoolExecutor

Timer負責管理 延遲任務 和 週期任務;缺陷以下:線程

  • 只會建立一個線程,若是任務耗時過長會影響其餘任務
  • Timer線程不捕獲異常, TimerTask拋出異常整個Timer任務都會取消。

若是要構建本身的調度器,能夠使用DelayQueue和ScheduledThreadPoolExecutor組合。code

異構任務
  • 定義: 不一樣類型的任務平均分配給每一個消費者。當消費者增長,在分配工做和協同工做的時候會存在考驗。
  • 只有大量相互獨立 而且 同構的任務併發處理才能最大限度的提高性能
ExecutorCompletionService
  • 一組Future任務,若是須要知道哪些完成了,須要不停的循環每一個Future的Get方法,很是繁瑣。
  • CompletionService 將 Executor 和BlockingQueue 功能融合在一塊兒
  • 多個 ExecutorCompletionService 能夠共享一個 Executor,
class Demo{
    final ExecutorService executor;

    void test(){
        CompletionService cs = new ExecutorCompletionService(executor); 
        
        for(...){
            cs.submit(new Callable(){
                //...
            });
        }

        for(...){
            // 返回的都是已經計算好結果的Callable
            Future<T> future = cs.take();
            future.get();
        }
    }
}
相關文章
相關標籤/搜索