Android超時控制方法及場景
阿新 • • 發佈:2018-12-30
剛剛和同事進行了一個非常有益的腦力訓練——怎樣控制超時。之前經常用,但並沒有仔細想過,這次梳理了一下。
想到了三個流派:
Future/Callable/FutureTask
Future和Callable自帶等待屬性,(FutureTask中)帶時間的get使用的是LockSupport做的等待(park、unpark)。這個方法的問題在於,需要用到Executor接口才能從Callable中拿到一個Future。
但是,FutureTask無需Executor。FutureTask繼承自Runnable和Future,所以既能有等待功能,又能直接放到Thread中,非常完美。
Object#wait/LockSupport/concurrent庫/Thread#join
主體思路就是自己寫Future中的PV操作。優勢在於更多的控制,隨性使用各種多執行緒方法,劣勢自然是麻煩、可能有問題。
擴充套件來說,這個方法有一個極大的好處,就是能夠1等n。比如,我當前有一個執行緒要等10個任務最多1s,這時用CountDownLatch就非常合適(join其實是順序的,可能不太好)。
回撥+標誌位
在UI中,主執行緒是不能用Object#wait、Future#get等方法的,此時的耗時操作+等待的方案就又有變化了。
偽碼:
- UIThread:
final Runnable afterwards = new Runnable(){
private AtomicBoolean mHasRunned = new AtomicBoolean(false);
public void run(){
if(mHasRunned.compareAndSet(false, true)){
doSomething();
}
}
}
new Thread(new TimeConsumingRunnable(new Callback(){
public void call(){
afterwards.run();
}
}).start();
someView.postDelay(afterwards, WAIT_TIME);
- TimeConsumingRunnable#run
try{
consumeTime();
} catch (Throwable thr){
callback.call();
}
思路就是afterwards在兩個位置(執行完耗時操作、超時)都呼叫,但是,用標記位保證程式碼只執行一遍。
這個的優勢在於,不會阻塞主執行緒,後面怎麼玩都是隨性而為;劣勢是理解和維護困難。