Android Thread Pool應用01在上一篇我們介紹到幾種Thread Pool的差異,在這邊我們就來進階一點的應用
上一篇舉出的範例都是如何開始執行Thread,就跟騎車開車一樣,除了知道要怎麼動以外,如何停下來也很重要的課題。這邊我測試了兩種讓Thread Pool停下來的方法,分別是shutdown/shutdownNow
首先這是我們自定義的Runnable,至於為何要多一個ExecutorService參數,待會用到的時候再解釋
這邊我們用FixedThreadPool做測試,如果有不清楚規則請到Android Thread Pool應用01了解
接下來我們範例的情境是這樣,我在執行完01~02時,手動離開Activity觸發onDestroy。
主要會想用這樣的情境來說明,是因為要模擬一般我們Call API也很有可遇到類似狀況,例如網路狀況不佳的時候可能等待3~5秒都還沒取到資料,通常使用者不想等了就會直接離開頁面,但總不能把值再塞回到UI(因為UI已經被回收了),這樣就可能會報錯。
先來試試看shutdown的效果,可以看到Log時間的部分,在onDestroy時觸發shutdown,目前為執行完的Thread仍會按原本的狀態執行到結束。但是注意如果在呼叫shutdown之後再execute是會直接crash的喔,就是因為Thread Pool已經處於shutdown的狀態。
接下來看看shutdownNow的效果,同樣在執行完01~02的時候(剛進入03~04等待Sleep結束),手動離開Activity觸發onDestroy,呼叫了shutdownNow之後,Sleep馬上被InterruptedException中斷,並且03~04執行完後05~06也不會再繼續了。
以上就是shutdown/shutdownNow實際狀況的比較
經過上面這段解釋聽起來好像已經可以做到停止Thread Pool,但好像還少了點什麼。
確實,Thread Pool停止了沒錯,但不論是shutdown或shutdownNow,在呼叫了之後都還是會有Thread持續的在進行,這樣就無法完全解決我們在上面講到Call API的那個情境。
ExecutorService就派上用場了,假設Sleep等待是Call API網路連線、資料傳遞的程式,那我們就可以在更新UI前先判斷Thread Pool是否已經中斷,若中斷就不更新UI了
又或者另一種做法
調整一下Runnable內容方便待會解說,改為兩階段的Sleep
Thread Pool執行改為使用submit的方式可以得到Future物件的回傳值(Future是什麼就不在這篇討論,因為還會牽扯到其他相關的物件,有機會在獨立寫一篇)
Future有提供cancel的方法可以直接取消目前的任務,未開始執行的任務會直接取消,已完成的任務則不受影響,至於進行中的任務則是依照cancel帶入的boolean參數決定
true是馬上中斷目前的任務,會觸發InterruptedException,所以第二階段的Sleep就立即被中斷
false的狀態則不會觸發InterruptedException,所以進行中的任務看起來不受影響
以上分享兩種處理進行中任務方式,有更進階的做法或者任何指正、意見歡迎提出討論