1. 程式人生 > >Android執行緒池詳解

Android執行緒池詳解

      最近在看OkHttp的原始碼,看著看著就看到了有執行緒池的地方,以前自己對這個東西就也就感到雲裡霧裡的,所以

想把執行緒池的知識點和原始碼完整的看一篇

  1.執行緒池有什麼用?

    a.重用執行緒池中存在的執行緒,避免因為執行緒的大量建立和銷燬所帶來的效能開銷 ,完成一項任務的時間T=建立線

程的時間+線上程中執行任務的時間+執行緒銷燬的時間, 而執行緒池的出現可以大大減少建立執行緒的時間和執行緒銷燬的

時間,從而提高app的效能
    
    b.能有限的控制執行緒池的最大併發數,並且大量的執行緒互相搶佔資源而導致的阻塞現象
    c.對執行緒池中執行緒進行有效的跟進,當我們不需要處理的時候可以將它shutdow掉
   並提供定時執行以及制定間隔迴圈執行, 

    2.ThreadPoolExcutor類詳解

   threadPoolExcutor是執行緒池中最核心的類,所以要想弄懂執行緒池一定要弄懂這個類

   (1)首先來了解一下構造方法:

public ThreadPoolExecutor(int corePoolSize,  
                              int maximumPoolSize,  
                              long keepAliveTime,  
                              TimeUnit unit,  
                              BlockingQueue<Runnable> workQueue,  
                              ThreadFactory threadFactory,  
                              RejectedExecutionHandler handler);  
   接下來看看具體每個引數是什麼意思?

   corePoolSize:核心執行緒池大小
   maximumPoolSize:最大執行緒池大小
   keepAliveTime:當一個執行緒無事可做,超過一定的時間(keepAliveTime)時,執行緒池會判斷,
                       如果當前執行的執行緒數大於 corePoolSize,那麼這個執行緒就被停掉。
   unit:keepAliveTime時間單位
   workQueue:阻塞任務佇列
   threadFactory:新建執行緒工廠
   handler:    當提交任務數超過maxmumPoolSize+workQueue之和時,任務會交給RejectedExecutionHandler來做拒絕處理

   (2)BlockingQueue詳解:用於儲存等待執行的執行緒任務的阻塞佇列
        ArrayBlockingQueue(少):是一個基於陣列結構的有界阻塞佇列,此佇列按 FIFO(先進先出)原則對元素進行排序。      
        LinkedBlockingQueue:一個基於連結串列結構的阻塞佇列,此佇列按FIFO (先進先出) 排序元素,吞吐量通常要高於ArrayBlockingQueue  靜態工廠方法Executors.newFixedThreadPool()使用了這個佇列,如果不執行佇列的大小,那麼該

佇列就是一個無界佇列,無界佇列的特徵見PriorityBlockingQueue                       
        SynchronousQueue:一個不儲存元素的阻塞佇列。每個插入操作必須等到另一個執行緒呼叫移除操作,否則插入操作一直處於阻塞狀態,它將任務直接提交給執行緒而不保持它們。在此,如果不存在可用於立即執行任務的執行緒,則試圖把任務加入佇列將失敗,因此會構造一個新的執行緒         
       PriorityBlockingQueue(少):一個具有優先順序的無限阻塞佇列,使用無界佇列將導致將導致在所有 corePoolSize 執行緒都忙時新任務在佇列中等待。這樣,建立的執行緒就不會超過 corePoolSize。(因此,maximumPoolSize和keepAliveTime的值也就無效了)
       
           
   (3)ThreadFactory作用:
       執行緒工廠,主要用來根據提交的新任務建立執行緒物件
      

 static class PicassoThreadFactory implements ThreadFactory {
         @SuppressWarnings("NullableProblems")
         public Thread newThread(Runnable r) {
           return new Thread(r);
        }
     }     


 

   (4)ThreadPoolExcutor的執行步驟

      ①、當呼叫 execute() 方法新增一個任務時,執行緒池會做如下判斷:
      a. 如果正在執行的執行緒數量小於 corePoolSize,那麼馬上建立執行緒執行這個任務;
      b. 如果正在執行的執行緒數量大於或等於 corePoolSize,那麼將這個任務放入佇列。
      c. 如果這時候佇列滿了,而且正在執行的執行緒數量小於 maximumPoolSize,那麼還是要建立執行緒執行這個任務;
      d. 如果佇列滿了,而且正在執行的執行緒數量大於或等於 maximumPoolSize,那麼執行緒池會丟擲異常,告訴呼叫者

“我不能再接受任務了”。
      ②、當一個執行緒完成任務時,它會從佇列中取下一個任務來執行。

      ③、當一個執行緒無事可做,超過一定的時間(keepAliveTime)時,執行緒池會判斷,如果當前執行的執行緒數大於

corePoolSize,那麼這個執行緒就被停掉。所以執行緒池的所有任務完成後,它最終會收縮到 corePoolSize 的大小。

這個過程說明,並不是先加入任務就一定會先執行。假設佇列大小為 4,corePoolSize為2,maximumPoolSize為6,

那麼當加入15個任務時,執行的順序類似這樣:首先執行任務 1、2,然後任務3~6被放入佇列。這時候佇列滿了,

任務7、8、9、10 會被馬上執行,而任務 11~15 則會丟擲異常。最終順序是:1、2、7、8、9、10、3、4、5、6。

當然這個過程是針對指定大小的ArrayBlockingQueue<Runnable>來說,如果無界佇列,那麼3-15的任務都會加到佇列


  3.ThreadPoolExcutor的使用

1)newFixedThreadPool(2)
      

     //指定了corePoolSize與maximumPoolSize為2
     ExecutorServicer pool=Executors.newFixedThreadPool(2);
     // 建立執行緒  
     Thread t1 = new MyThread();  
     Thread t2 = new MyThread();  
     Thread t3 = new MyThread();  
     // 將執行緒放入池中進行執行  
     pool.execute(t1);  
     pool.execute(t2);  
     pool.execute(t3);  
     // 關閉執行緒池  
     pool.shutdown();  
     private class MtThread extends Thread{...}  
     
      
   (2)單任務執行緒池newSingleThreadExecutor()
    
//只會有一個執行緒執行
     ExecutorService pool = Executors.newSingleThreadExecutor();

    
    
 (3).不限制大小,可變尺寸的執行緒池newCachedThreadPool()
   
//可根據需要建立新執行緒的執行緒池,但是在以前構造的執行緒可用時將重用它們。
    ExecutorService pool = Executors.newCachedThreadPool();
(4).延遲執行緒池,newScheduledThreadPool
       // 建立一個執行緒池,它可安排在給定延遲後執行命令或者定期地執行。  
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);  
        // 建立實現了Runnable介面物件,Thread物件當然也實現了Runnable介面  
        Thread t1 = new MyThread();  
        Thread t2 = new MyThread();  
        Thread t3 = new MyThread();  
        // 將執行緒放入池中進行執行  
        pool.execute(t1);  
        // 使用延遲執行風格的方法  
        pool.schedule(t2, 1000, TimeUnit.MILLISECONDS);  
        pool.schedule(t3, 10, TimeUnit.MILLISECONDS);  
         
        // 關閉執行緒池  
        pool.shutdown(); 
以上就是Executors類的四種靜態建立執行緒池的方法,如果不能滿足需求,還可以通過例項化ThreadPoolThread

來自定義執行緒池

  (5)ThreadPoolExecutor中幾個重要的方法

① execute(Runnable r):向執行緒池新增一個執行緒任務
   ② Future<?> submit(Runnable r):向執行緒池新增一個執行緒任務,可以返回任務執行結果
   ③ shutdown():關閉執行緒池,不接收新的任務,關閉後,正在等待執行的任務不受任何影響,會正常執行,無返回值!
   ④ shutdownNow():關閉執行緒池,也不接收新的Task,並停止正等待執行的Task(也就是說,
   執行到一半的任務將正常執行下去),最終還會給你返回一個正在等待執行但執行緒池關閉卻沒有被執行的Task集合

   我們執行Runnable任務,他的run()方法是沒有返回值的,那如果我們想要執行完一個任務,並且能夠拿到一個返回值結果,那麼應該怎麼做呢?這個在我的另一篇部落格已經將的很清楚了就不重複講了Future和Callable詳解

相關推薦

Android執行

      最近在看OkHttp的原始碼,看著看著就看到了有執行緒池的地方,以前自己對這個東西就也就感到雲裡霧裡的,所以 想把執行緒池的知識點和原始碼完整的看一篇   1.執行緒池有什麼用?     

Android(執行二) 執行

  我們在ListView中需要下載資源時,贊不考慮快取機制,那麼每一個Item可能都需要開啟一個執行緒去下載資源(如果沒有執行緒池),如果Item很多,那麼我們可能就會無限制的一直建立新的執行緒去執行下載任務,最終結果可能導致,應用卡頓、手機反應遲鈍!最壞的結果是,使用者

ExecutorService執行

對執行緒池 “池”的理解 可以理解為工廠,如果工廠生產斧頭,小王從工廠借了一把,當小王用完了,還給工廠,之後小李也可以借去用 複用已有資源 控制資源總量 你一個任務過來了,我發現池子裡有沒事幹並且還活著的執行緒,來,拿去用,我也不用費事給你建立一條執行緒了,要知道

Java 執行

構造一個執行緒池為什麼需要幾個引數?如果避免執行緒池出現OOM?Runnable和Callable的區別是什麼?本文將對這些問題一一解答,同時還將給出使用執行緒池的常見場景和程式碼片段。 基礎知識 Executors建立執行緒池 Java中建立執行緒池很簡單,只需要呼叫Ex

Java執行及例項

前言 多執行緒的非同步執行方式,雖然能夠最大限度發揮多核計算機的計算能力,但是如果不加控制,反而會對系統造成負擔。執行緒本身也要佔用記憶體空間,大量的執行緒會佔用記憶體資源並且可能會導致Out of Memory。即便沒有這樣的情況,大量的執行緒回收也會給GC帶來很大的壓力

執行

內容目錄 TreadPoolexecutor原始碼解析 類關係圖 Executor介面 ExecutorService介面 AbstractExecutorService 成員變數 建構函式 Worker類解析 Worker簡介 成員變數 構造方法 e

ThreadPoolExecutor機制&執行

一、概述1.執行緒池可以解決兩個不同問題:由於減少了每個任務呼叫的開銷,它們通常可以在執行大量非同步任務時提供增強的效能,並且還可以提供繫結和管理資源(包括執行任務集時使用的執行緒)的方法。每個 ThreadPoolExecutor 還維護著一些基本的統計資料,如完成的任務數;2.ThreadPoolExec

雜談——Java執行

在一個應用程式中,我們無可避免地需要多次使用執行緒,也就意味著,我們需要多次建立並銷燬執行緒。而建立並銷燬執行緒的過程勢必會消耗記憶體。 舉個例子,假設我們要去爬三百主流媒體網站,每天要抓一次資料,平均每次開銷50毫秒,處理開銷2毫秒,則可以開二十五個執行緒,假設每個網站有十個請求,那麼三百個網

四大執行

new Thread 的弊端 首先看一段程式碼: /** * Created by Zero on 2017/8/30. */ public class ThreadTest { public static void main(String[] args) {

Tomcat 連線數與執行 | BIO/NIO有何不同 | 簡談Kafka中的NIO網路通訊模型

前言 在使用tomcat時,經常會遇到連線數、執行緒數之類的配置問題,要真正理解這些概念,必須先了解Tomcat的聯結器(Connector)。 在前面的文章 詳解Tomcat配置檔案server.xml 中寫到過:Connector的主要功能,是接收連線請求,建立Req

【搞定Java併發程式設計】第28篇:Java中的執行

上一篇:Java中的併發工具類之執行緒間交換資料的 Exchanger 本文目錄: 1、執行緒池的實現原理  2、執行緒池的使用 2.1、執行緒池的建立 2.2、向執行緒池提交任務 2.3、關閉執行緒池 2.4、合理地配置執行緒池 2.5、執行緒池的監控

Java併發:執行(ThreadPoolExecutor)

/** * 主池控制狀態ctl是包含兩個概念欄位的原子整數: workerCount:指有效的執行緒數量; * runState:指執行狀態,執行,關閉等。為了將workerCount和runState用1個int來表示, * 我們限制workerCount範圍為(2 ^ 29) - 1,即用int的低

Java執行,看這篇就夠了!

構造一個執行緒池為什麼需要幾個引數?如果避免執行緒池出現OOM?Runnable和Callable的區別是什麼?本文將對這些問題一一解答,同時還將給出使用執行緒池的常見場景和程式碼片段。 基礎知識 Executors建立執行緒池 Java中建立執行緒池很簡單,只需要呼叫Execu

【本人禿頂程式設計師】Java執行,看這篇就夠了!

←←←←←←←←←←←← 快!點關注!!! 構造一個執行緒池為什麼需要幾個引數?如果避免執行緒池出現OOM?Runnable和Callable的區別是什麼?本文將對這些問題一一解答,同時還將給出使用執行緒池的常見場景和程式碼片段。 基礎知識 Executors建立執行緒池 J

Java多執行-----執行

   1. 執行緒池的實現原理       提交一個任務到執行緒池中,執行緒池的處理流程如下: 判斷執行緒池裡的核心執行緒是否都在執行任務,如果不是(核心執行緒空閒或者還有核心執行緒沒有被建立)則建立一個新的工作執行緒來執行任務。如果核心執行緒都在執

java 執行及四種執行用法介紹

java 執行緒池詳解      Executor框架是一種將執行緒的建立和執行分離的機制。它基於Executor和ExecutorService介面,及這兩個介面的實現類ThreadPoolExecutor展開,Executor有一個內部執行緒池,並提供了將任務傳遞到池中

java四種執行與使用

1、什麼是執行緒池 在解釋什麼是執行緒池前,再贅述下什麼是執行緒: 1、執行緒:現代作業系統在執行一個程式時, 會為其建立一個程序。 例如, 啟動一個Java程式, 作業系統就會建立一個Java進 程。 現代作業系統排程的最小單元是執行緒, 也叫輕量級程序(Light

各種Map和執行

視訊是公司週會分享時錄的,請參考。 目錄: 1、Map - HashMap - LinkedHashMap - ConcurrentHaspMap - ArrayMap - TreeMa

JAVA四種執行

執行緒池採取上述的流程進行設計是為了減少獲取全域性鎖的次數。線上程池完成預熱(當前執行的執行緒數大於或等於corePoolSize)之後,幾乎所有的excute方法呼叫都執行步驟2。 執行緒池的作用: 1. 執行緒池作用就是限制系統中執行執行緒的數量。 2. 根據系統的環境情況,可以自動或手動設定執行緒數量

java執行

在前面的文章中,我們使用執行緒的時候就去建立一個執行緒,這樣實現起來非常簡便,但是就會有一個問題:   如果併發的執行緒數量很多,並且每個執行緒都是執行一個時間很短的任務就結束了,這樣頻繁建立執行緒就會大大降低系統的效率,因為頻繁建立執行緒和銷燬執行緒需要時間。   那麼