1. 程式人生 > >Android ExecutorService介紹

Android ExecutorService介紹

執行一個非同步任務你還是new Thread嗎?你知道使用new Thread的弊端嗎?
  1. 每次new Thread新建物件效能差。
  2. 執行緒缺乏統一管理,可能無限制新建執行緒,相互之間競爭,及可能佔用過多系統資源導致宕機或oom。
  3. 缺乏更多功能,如定時執行、定期執行、執行緒中斷。
看了以上我推薦使用ExecutorService

相比new Thread,Java提供的四種執行緒池的好處在於:

  1. 重用存在的執行緒,減少物件建立、消亡的開銷,效能佳。
  2. 可有效控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
  3. 提供定時執行、定期執行、單執行緒、併發數控制等功能。
Java通過Executors提供四種執行緒池,分別為:

1.newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。

2.newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。

3.newScheduledThreadPool 建立一個定長執行緒池,支援定時及週期性任務執行。

4.newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。

詳解:

(1). newCachedThreadPool

建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。

(2). newFixedThreadPool

建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待,
定長執行緒池的大小最好根據系統資源進行設定。如Runtime.getRuntime().availableProcessors()。可參考PreloadDataCache。

(3) newScheduledThreadPool

建立一個定長執行緒池,支援定時及週期性任務執行;ScheduledExecutorService比Timer更安全,功能更強大

(4)、newSingleThreadExecutor

建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。現行大多數GUI程式都是單執行緒的。Android中單執行緒可用於資料庫操作,檔案操作,應用批量安裝,應用批量刪除等不適合併發但可能IO阻塞性及影響UI執行緒響應的操作

execute(Runnable)

方法 execute(Runnable) 接收1個 java.lang.Runnable 物件作為引數,並且以非同步的方式執行它,使用這種方式沒有辦法獲取執行 Runnable 之後的結果,如果你希望獲取執行之後的返回值,就必須使用 接收 Callable 引數的 execute() 方法

submit(Runnable)

方法 submit(Runnable) 同樣接收一個 Runnable 的實現作為引數,但是會返回一個 Future 物件。這個 Future 物件可以用於判斷 Runnable 是否結束執行

submit(Callable)

方法 submit(Callable) 和方法 submit(Runnable) 比較類似,但是區別則在於它們接收不同的引數型別。Callable 的例項與 Runnable 的例項很類似,但是 Callable 的 call() 方法可以返回壹個結果。方法 Runnable.run() 則不能返回結果。

Callable 的返回值可以從方法 submit(Callable) 返回的 Future 物件中獲取

inVokeAny()

方法 invokeAny() 接收壹個包含 Callable 物件的集合作為引數。呼叫該方法不會返回 Future 物件,而是返回集合中某壹個 Callable 物件的結果,而且無法保證呼叫之後返回的結果是哪壹個 Callable,只知道它是這些 Callable 中壹個執行結束的 Callable 物件。
如果壹個任務執行完畢或者丟擲異常,方法會取消其它的 Callable 的執行

invokeAll()

方法 invokeAll() 會呼叫存在於引數集合中的所有 Callable 物件,並且返回壹個包含 Future 物件的集合,你可以通過這個返回的集合來管理每個 Callable 的執行結果。

需要注意的是,任務有可能因為異常而導致執行結束,所以它可能並不是真的成功運行了。但是我們沒有辦法通過 Future 物件來了解到這個差異

ExecuteService 服務的關閉

使用 ExecutorService 完畢之後,我們應該關閉它,這樣才能保證執行緒不會繼續保持執行狀態。

舉例來說,如果你的程式通過 main() 方法啟動,並且主執行緒退出了你的程式,如果你還有壹個活動的 ExecutorService 存在於你的程式中,那麼程式將會繼續保持執行狀態。存在於 ExecutorService 中的活動執行緒會阻止Java虛擬機器關閉。

為了關閉在 ExecutorService 中的執行緒,你需要呼叫 shutdown() 方法。ExecutorService
並不會馬上關閉,而是不再接收新的任務,壹但所有的執行緒結束執行當前任務,ExecutorServie 才會真的關閉。

所有在呼叫 shutdown() 方法之前提交到 ExecutorService 的任務都會執行。
如果你希望立即關閉 ExecutorService,你可以呼叫 shutdownNow() 方法。這個方法會嘗試馬上關閉所有正在執行的任務,並且跳過所有已經提交但是還沒有執行的任務。但是對於正在執行的任務,是否能夠成功關閉它是無法保證的,有可能他們真的被關閉掉了,也有可能它會壹直執行到任務結束。這是壹個最好的嘗試