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/shutdownNow
先来试试看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了
又或者另一种做法
Future cancel
调整一下Runnable内容方便待会解说,改为两阶段的Sleep
Thread Pool执行改为使用submit的方式可以得到Future物件的回传值(Future是什么就不在这篇讨论,因为还会牵扯到其他相关的物件,有机会在独立写一篇)
Future有提供cancel的方法可以直接取消目前的任务,未开始执行的任务会直接取消,已完成的任务则不受影响,至于进行中的任务则是依照cancel带入的boolean参数决定
true是马上中断目前的任务,会触发InterruptedException,所以第二阶段的Sleep就立即被中断
false的状态则不会触发InterruptedException,所以进行中的任务看起来不受影响
以上分享两种处理进行中任务方式,有更进阶的做法或者任何指正、意见欢迎提出讨论