溫馨提示×

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

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

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

發(fā)布時(shí)間:2020-09-16 03:21:51 來(lái)源:腳本之家 閱讀:183 作者:wuzhaohui026 欄目:移動(dòng)開(kāi)發(fā)

Android 的線程和線程池

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

主線程和子線程

主線程是指進(jìn)程所擁有的線程。Android 中主線程交 UI 線程,主要作用是運(yùn)行四大組件以及處理它們和用戶的交互;子線程的作業(yè)則是執(zhí)行耗時(shí)任務(wù)。

Android 中的線程形態(tài)

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

  • onPreExcute(),在主線程中執(zhí)行,在異步任務(wù)執(zhí)行之前,此方法會(huì)被調(diào)用,一般可以用于做一些準(zhǔn)備工作。
  • doInBackground(Params...params),在線程池中執(zhí)行,此方法用于執(zhí)行異步任務(wù),params 參數(shù)表示異步任務(wù)的輸入?yún)?shù)。在此方法中可以通過(guò) publishProgress 方法來(lái)更新任務(wù)的進(jìn)度,publishProgress 方法會(huì)調(diào)用 onProgressUpdate 方法,另外此方法需要返回計(jì)算結(jié)果給 onPostExecute 方法。
  • onProgressUpdate(Progress...values),在主線程中執(zhí)行,當(dāng)后臺(tái)任務(wù)的執(zhí)行進(jìn)度發(fā)生改變時(shí)此方法會(huì)被調(diào)用。
  • onPostExecute(Resukt result),在主線程中執(zhí)行,在異步任務(wù)執(zhí)行之后,此方法會(huì)被調(diào)用,其中 result 參數(shù)是后臺(tái)任務(wù)的返回值,即 doInBackground 的返回值。

onPreExcute 先執(zhí)行,接著是 doInBackground,最后才是 onPostExecute。 當(dāng)異步任務(wù)被取消時(shí),onCancelled() 方法會(huì)被調(diào)用,這個(gè)時(shí)候 onPostExecute 則不會(huì)被調(diào)用。

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

  • AsyncTask 的類必須在主線程中加載;
  • AsyncTask 的對(duì)象必須在 UI 線程中創(chuàng)建;
  • 不要在程序中直接調(diào)用 onPreExecute、onPostExecute、doInBackground 和 onProgressUpdate 方法。
  • 一個(gè) AsyncTask 對(duì)象只能執(zhí)行一次,即只能調(diào)用一次 execute 方法,否則會(huì)報(bào)運(yùn)行時(shí)異常。
  • 在 Android 1.6之前,AsyncTask 是串行執(zhí)行任務(wù)的,Android 1.6的時(shí)候 AsyncTask 開(kāi)始采用線程池處理并行任務(wù),但是從 Android 3.0開(kāi)始為了避免 AsyncTask 所帶來(lái)的并發(fā)錯(cuò)誤,AsyncTask 又采用一個(gè)線程來(lái)串行執(zhí)行任務(wù)。但是在 Android 3.0 以及后續(xù)的版本中,仍然可以通過(guò) AsyncTask 的 executeOnExecutor 方法來(lái)并行地執(zhí)行任務(wù)。

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

4、HandlerThread HandlerThread 繼承了 Thread,是一種可以使用 Handler 的 Thread, 它的實(shí)現(xiàn)就是在 run 方法中通過(guò) Looper.prepare() 來(lái)創(chuàng)建消息隊(duì)列,并通過(guò) Looper.loop() 來(lái)開(kāi)啟消息循環(huán)。

與普通的 Thread 相比,普通 Thread 主要用于在 run 方法中執(zhí)行一個(gè)耗時(shí)任務(wù),而 HandlerThread 在內(nèi)部創(chuàng)建了消息隊(duì)列,外界需要通過(guò) Handler 的消息方式來(lái)通知 HandlerThread 執(zhí)行一個(gè)具體的任務(wù)。

由于 HandlerThread 的 run 方法是一個(gè)無(wú)限循環(huán),因此當(dāng)明確不需要在使用 HandlerThread 時(shí),可以通過(guò)它的 quit 或者 quitSafely 方法來(lái)終止線程的執(zhí)行。

5、IntentService IntentService 是一種特殊的 Service,繼承了 Service 并且是一個(gè)抽象類,必須創(chuàng)建它的子類才能使用 IntentService。IntentService可用于執(zhí)行后臺(tái)耗時(shí)任務(wù),任務(wù)執(zhí)行后會(huì)自動(dòng)停止,并且它的優(yōu)先級(jí)比單純的線程要高很多,不容易被系統(tǒng)殺死。在實(shí)現(xiàn)上,IntentService 封裝了 HandlerThread 和 Handler。

Android 中的線程池

線程池的優(yōu)點(diǎn)

  • 重用線程池中的線程,避免因?yàn)榫€程的創(chuàng)建和銷毀所帶來(lái)的性能開(kāi)銷;
  • 能有效控制線程池的最大并發(fā)數(shù),避免大量的線程之間因互相搶占系統(tǒng)資源而導(dǎo)致的阻塞現(xiàn)象;
  • 能夠?qū)€程進(jìn)行簡(jiǎn)單的管理,并提供定時(shí)執(zhí)行以及指定間隔循環(huán)執(zhí)行等功能。

ThreadPoolExecutor ThreadPoolExecutor 是線程的真正實(shí)現(xiàn)。

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

ThreadPoolExecutor 執(zhí)行任務(wù)時(shí)遵循的規(guī)則

  • 如果線程池中的線程數(shù)量未達(dá)到核心線程的數(shù)量,那么會(huì)直接啟動(dòng)一個(gè)核心線程來(lái)執(zhí)行任務(wù);
  • 如果線程池中的線程數(shù)量已經(jīng)達(dá)到或者超過(guò)核心線程的數(shù)量,那么任務(wù)會(huì)被插入到任務(wù)隊(duì)列中排隊(duì)等待執(zhí)行;
  • 如果在步驟2中無(wú)法將任務(wù)插入到任務(wù)隊(duì)列中,這往往是由于任務(wù)隊(duì)列已滿,這個(gè)時(shí)候如果線程數(shù)量為達(dá)到線程池規(guī)定的最大值,那么會(huì)立刻啟動(dòng)一個(gè)非核心線程來(lái)執(zhí)行任務(wù)。
  • 如果步驟3中線程數(shù)量已經(jīng)達(dá)到線程池規(guī)定的最大值,那么就拒絕執(zhí)行此任務(wù), ThreadPoolExecutor 會(huì)調(diào)用 RejectedExecutionHandler 的 rejectedExecution 方法來(lái)通知調(diào)用者。

線程池的分類

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

系統(tǒng)預(yù)置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 后執(zhí)行 command
  scheduledThreadPool.schedule(command,2000,TimeUnit.MILLISECONDS);
  // 延遲10ms,每個(gè)1000ms執(zhí)行一次 command
  scheduledThreadPool.scheduleAtFixedRate(command,10,1000,TimeUnit.MILLISECONDS);

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

  }

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI