1. 程式人生 > >Android超時控制方法及場景

Android超時控制方法及場景

剛剛和同事進行了一個非常有益的腦力訓練——怎樣控制超時。之前經常用,但並沒有仔細想過,這次梳理了一下。
想到了三個流派:

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在兩個位置(執行完耗時操作、超時)都呼叫,但是,用標記位保證程式碼只執行一遍。
這個的優勢在於,不會阻塞主執行緒,後面怎麼玩都是隨性而為;劣勢是理解和維護困難。