JAVA 線程協同合作(等待子線程運行完了 繼續線面主線程的運行)

Java中自帶的countdownLatch 可以設置同時併發的線程數,一旦併發的線程數達到了0 countdownlatch.countdown() ,就可以繼續走下面的線程 countdownlatch.await()方法等待,比如主線程必須等待子線程操作了之後 獲取到子線程的數據,再繼續下面的操作,此時可以用countdownlatch類。

第二種方式

private static Handler sHandler = new Handler(Looper.getMainLooper());

/**
 * 在主線程運行runnable
 *
 * @param waitUntilDone 直到等待完成
 * @param job           runnable接口
 */
public static void dispatch(final boolean waitUntilDone, final Runnable job) {
    if (job == null) {
        return;
    }

    //主線程的標誌
    boolean alreadyInMain = Thread.currentThread() == Looper.getMainLooper().getThread();
    if (alreadyInMain) {
        //如果是在主線程的話,直接運行
        job.run();
    } else {
        //如果不是在主線程的話,那麼需要用到handler異步處理消息機制
        //這個Semaphore被稱爲信息量,http://www.jianshu.com/p/0090341c6b80(我暫時還沒有看懂)
        final Semaphore semaphore = new Semaphore(0);
        //在主線程創建handlder
        sHandler.post(() -> {
            job.run();//主線程運行

            if (waitUntilDone) {
                semaphore.release();//使得信息量容許的線程數加1
            }
        });

        if (!waitUntilDone)
            return;

        try {
            semaphore.acquire();//使得信息量容許的線程數減1
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public static void dispatch(Runnable job) {
    dispatch(false, job);
}

public static void postDelayed(Runnable job, long delayMillis) {
    if (delayMillis < 0L) {
        delayMillis = 0L;
    }

    sHandler.postDelayed(job, delayMillis);
}

public static void release() {
    if (sHandler != null) {
        sHandler.removeCallbacksAndMessages(null);
    }
}

 

 

 

主線程等待多個子線程執行完才繼續執行,以下是我能想到的幾種方法,歡迎討論、指正。


1.閉鎖CountDownLatch
閉鎖是典型的等待事件發生的同步工具類,將閉鎖的初始值設置爲與子線程數目相同,每個子線程執行完成都調用CountDown()方法,主線程調用await()方法等待計數值變爲零之後恢復繼續執行。

 

2.線程間同步方法
假設有N個子線程,每個子線程執行完成都將一個全局的原子變量加1,待某個線程將原子變量加到N之後,則利用以下三種方法將主線程喚醒。

互斥信號量Semaphore:主線程申請佔用信號量失敗阻塞,由子線程釋放信號量喚醒。
阻塞隊列BlockingQueue:主線程嘗試從空隊列取東西失敗阻塞,由子線程放入東西喚醒。
條件隊列:主線程wait/await在內置或顯式的條件隊列上,由子線程notify/signal喚醒。
 

3.Future的get()方法
提交子線程到線程池執行的時候維護好所有子線程的Future對象,主線程中循環調用所有Future對象的get方法等待子線程執行完成並返回結果。

 

4.CompletionService的take()方法
提交所有子線程到ExecutorCompletionService線程池執行,主線程通過其take方法等待所有子線程執行完成並返回結果。

 

5.Thread的join()方法
創建Thread對象並start啓動之後維護好所有子線程的Thread對象,在主線程中循環調用所有子線程這個Thread對象的join方法,等待所有子線程執行完成。

 

6.柵欄CyclicBarrier
柵欄是典型的等待所有線程到達同一柵欄位置的同步工具類。可以在所有子線程的結束位置設置柵欄,待所有子線程達到柵欄位置後執行指定的Runnable線程,此方法並不是嚴格意義的等待所有子線程執行完成後繼續執行主線程,而是執行另一個線程。

 

7.線程池的awaitTermination()方法
ExecutorService的awaitTermination()方法定義如下:

boolean awaitTermination(long timeout,

                         TimeUnit unit)

                         throwsInterruptedException

這個方法作用是等待提交的任務全部執行完成,但是需要設置超時時間,若超時則會返回false,所以並不能準確估計需要等待多長時間。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章