中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

淺談Android 的線程和線程池的使用

發布時間:2020-09-16 03:21:51 來源:腳本之家 閱讀:183 作者:wuzhaohui026 欄目:移動開發

Android 的線程和線程池

從用途上分,線程分為主線程和子線程;主線程主要處理和界面相關的事情,子線程則往往用于耗時操作。

主線程和子線程

主線程是指進程所擁有的線程。Android 中主線程交 UI 線程,主要作用是運行四大組件以及處理它們和用戶的交互;子線程的作業則是執行耗時任務。

Android 中的線程形態

1、AsyncTask AsyncTask 是一種輕量級的異步任務類,可以在線程池中執行后臺任務,然后把執行的進度和最終結果傳遞給主線程并在主線程中更新 UI, AsyncTask 是一個抽象的泛型類,提供了 Params(參數的類型)、Progress(后臺任務執行進度的類型) 和 Result(后臺任務的返回結果的類型) 這三個泛型參數, AsyncTask 提供了4個核心方法

  • onPreExcute(),在主線程中執行,在異步任務執行之前,此方法會被調用,一般可以用于做一些準備工作。
  • doInBackground(Params...params),在線程池中執行,此方法用于執行異步任務,params 參數表示異步任務的輸入參數。在此方法中可以通過 publishProgress 方法來更新任務的進度,publishProgress 方法會調用 onProgressUpdate 方法,另外此方法需要返回計算結果給 onPostExecute 方法。
  • onProgressUpdate(Progress...values),在主線程中執行,當后臺任務的執行進度發生改變時此方法會被調用。
  • onPostExecute(Resukt result),在主線程中執行,在異步任務執行之后,此方法會被調用,其中 result 參數是后臺任務的返回值,即 doInBackground 的返回值。

onPreExcute 先執行,接著是 doInBackground,最后才是 onPostExecute。 當異步任務被取消時,onCancelled() 方法會被調用,這個時候 onPostExecute 則不會被調用。

2、AsyncTask 在具體的使用過程中的一些限制條件

  • AsyncTask 的類必須在主線程中加載;
  • AsyncTask 的對象必須在 UI 線程中創建;
  • 不要在程序中直接調用 onPreExecute、onPostExecute、doInBackground 和 onProgressUpdate 方法。
  • 一個 AsyncTask 對象只能執行一次,即只能調用一次 execute 方法,否則會報運行時異常。
  • 在 Android 1.6之前,AsyncTask 是串行執行任務的,Android 1.6的時候 AsyncTask 開始采用線程池處理并行任務,但是從 Android 3.0開始為了避免 AsyncTask 所帶來的并發錯誤,AsyncTask 又采用一個線程來串行執行任務。但是在 Android 3.0 以及后續的版本中,仍然可以通過 AsyncTask 的 executeOnExecutor 方法來并行地執行任務。

3、AsyncTask 的工作原理 AsyncTask 中有兩個線程池(SerialExecutor 和 THREAD_POOL_EXECUTOR) 和一個 Handler(InternalHandler),線程池 SerialExecutor 用于任務的排隊,線程池 THREAD_POOL_EXECUTOR 用于真正地執行任務,InternalHandler 用于將執行環境從線程池切換到主線程。

4、HandlerThread HandlerThread 繼承了 Thread,是一種可以使用 Handler 的 Thread, 它的實現就是在 run 方法中通過 Looper.prepare() 來創建消息隊列,并通過 Looper.loop() 來開啟消息循環。

與普通的 Thread 相比,普通 Thread 主要用于在 run 方法中執行一個耗時任務,而 HandlerThread 在內部創建了消息隊列,外界需要通過 Handler 的消息方式來通知 HandlerThread 執行一個具體的任務。

由于 HandlerThread 的 run 方法是一個無限循環,因此當明確不需要在使用 HandlerThread 時,可以通過它的 quit 或者 quitSafely 方法來終止線程的執行。

5、IntentService IntentService 是一種特殊的 Service,繼承了 Service 并且是一個抽象類,必須創建它的子類才能使用 IntentService。IntentService可用于執行后臺耗時任務,任務執行后會自動停止,并且它的優先級比單純的線程要高很多,不容易被系統殺死。在實現上,IntentService 封裝了 HandlerThread 和 Handler。

Android 中的線程池

線程池的優點

  • 重用線程池中的線程,避免因為線程的創建和銷毀所帶來的性能開銷;
  • 能有效控制線程池的最大并發數,避免大量的線程之間因互相搶占系統資源而導致的阻塞現象;
  • 能夠對線程進行簡單的管理,并提供定時執行以及指定間隔循環執行等功能。

ThreadPoolExecutor ThreadPoolExecutor 是線程的真正實現。

public ThreadPoolExecutor(int corePoolSize,
              int maximumPoolSize,
              long keepAliveTime,
              TimeUnit unit,
              BlockingQueue<Runnable> workQueue,
              ThreadFactory threadFactory)
  • corePoolSize 線程池的核心線程數,默認情況下,核心線程會在線程池中一直存活,及時處于閑置狀態。
  • maximumPoolSize 線程池所能容納的最大線程數,當活動線程數達到這個數值后,后續的新任務將會被阻塞。
  • keepAliveTime 非核心線程閑置時的超時時長,超過這個時長,非核心線程就會被回收。
  • unit 用于指定 keepAliveTime 參數的時間單位,這是一個枚舉,常用的有 TimeUnit、MILLSECONDS(毫秒)、TimeUnit.SECONDS(秒) 以及 TimeUnit.MINUTES(分鐘)。
  • workQueue 線程池中的任務隊列,通過線程池的 execute 方法提交的 Runnable 對象會存儲在這個參數中。
  • threadFactory 線程工廠,為線程池通過創建新線程的功能。ThreadFactory 是一個接口,只有 一個方法:Thread newThread(Runnable r)。

ThreadPoolExecutor 執行任務時遵循的規則

  • 如果線程池中的線程數量未達到核心線程的數量,那么會直接啟動一個核心線程來執行任務;
  • 如果線程池中的線程數量已經達到或者超過核心線程的數量,那么任務會被插入到任務隊列中排隊等待執行;
  • 如果在步驟2中無法將任務插入到任務隊列中,這往往是由于任務隊列已滿,這個時候如果線程數量為達到線程池規定的最大值,那么會立刻啟動一個非核心線程來執行任務。
  • 如果步驟3中線程數量已經達到線程池規定的最大值,那么就拒絕執行此任務, ThreadPoolExecutor 會調用 RejectedExecutionHandler 的 rejectedExecution 方法來通知調用者。

線程池的分類

  • FixedThreadPool 通過 Executors 的 newFixedThreadPool 方法來創建。是一種線程數量固定的線程池,當線程處于空閑狀態時并不會被回收,除非線程池被關閉。FixedThreadPool 中只有核心線程并且這些核心線程沒有超時機制,另外任務隊列也是沒有大小限制。
  • CachedThreadPool 通過 Executors 的 newCachedThreadPool 方法來創建。是一種線程數量不定的線程池,只有非核心線程,最大線程數為 Integer.MAX_VALUE。線程池中的空閑線程都有超時機制,這個超時時長為60秒,超過60秒閑置線程就會被回收。CachedThreadPool 的任務隊列相當于一個空集合,這樣會導致任何任務都會被立即執行。
  • ScheduledThreadPool 通過 Executors 的 newScheduledThreadPool 方法來創建。它的核心線程數量是固定的,而非核心線程數是沒有限制的,并且當非核心線程閑置時會被立即回收。ScheduledThreadPool 這類線程池主要用于執行定時任務和具有固定周期的重復任務。
  • SingleThreadExecutor 通過 Executors 的 newSingleThreadExecutor 方法來創建。這類線程池內部只有一個核心線程,它確保所有的任務都在同一個線程中按順序執行。SingleThreadExecutor 的意義在于統一所有的外界任務到一個線程中,這使得在這些任務之間不需要處理線程同步的問題。

系統預置4種線程池的典型使用方法:

Runnable command = new Runnable(){
    @Override
    public void run(){
      SystemClock.sleep(2000);
    }

  ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
  fixedThreadPool.execute(command);

  ExecutorService cachedThreadPool =Executors.newCachedThreadPool();
  cachedThreadPool.execute(command);

  ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4);
  // 2000ms 后執行 command
  scheduledThreadPool.schedule(command,2000,TimeUnit.MILLISECONDS);
  // 延遲10ms,每個1000ms執行一次 command
  scheduledThreadPool.scheduleAtFixedRate(command,10,1000,TimeUnit.MILLISECONDS);

  ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
  singleThreadExecutor.execute(command);

  }

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

迭部县| 伊川县| 冕宁县| 临洮县| 贺兰县| 天全县| 清水河县| 阿拉善左旗| 天台县| 玉屏| 河津市| 三门峡市| 喀喇沁旗| 新余市| 色达县| 华亭县| 克什克腾旗| 筠连县| 墨竹工卡县| 建德市| 全椒县| 河间市| 博野县| 沛县| 呼和浩特市| 德惠市| 伽师县| 延边| 铜梁县| 马山县| 松原市| 和田县| 龙岩市| 略阳县| 湖口县| 顺平县| 宾阳县| 屏边| 衢州市| 内江市| 元氏县|