java開發-批量線程同步

問題背景描述

啓用線程池批量執行一些定時任務,每次需要這些任務都執行完,再開始下一次的任務批量執行。
如下圖:
這裏寫圖片描述

如上圖的業務描述,如果不對批量的線程任務做原子性限制,假如第一次執行定時任務,某條線程任務執行的比較慢,8分鐘了還沒執行完。第二次執行定時任務時,由於該條任務數據庫數據狀態沒有改變,還會被讀取出來,導致重複執行。所以,需要對每次定時任務的這些批量任務加原子性限制,只有當前這次的批量任務都做完了,才能開始下一次批量任務。

解決方案

使用CountDownLatch工具類,可以實現“批量線程”同步。
CountDownLatch類可以通過await()方法,讓當前線程處於一直阻塞等待狀態,直到通過countDown() 方法將線程的計數器減爲0。在初始化CountDownLatch時,指定線程計數總數。

public void executor() {
        System.out.println("---------任務調度開始-------------");

        CountDownLatch latch = new CountDownLatch(3);
        for (TSysTask taskInfo : taskList) {
            AbstractSysTask task = new MyTask();
            sysTaskThreadPool.execute(task);
        }

        System.out.println("---------任務調度中-------------");

        try {
            latch.await();
        } catch (InterruptedException e) {
            logger.error(e.getMessage(), e);

        System.out.println("---------任務調度結束-------------");
    }

分析:
(1)只有通過調用 latch.await() 方法纔會實現“批量線程”同步;不調用這個方法,是沒有任何效果的;
也就是說,即便初始化時指定了計數器個數,如果不調用 latch.await() 方法,怎麼調用countDown方法都沒用的。
(2)調用 latch.await() 方法,CountDownLatch工具類會立刻將當前方法 executor 鎖定給當前線程,此時別的其他線程是無法執行executor方法的,得排隊等着。直到通過countDown方法將同步計數器減爲0.
(3)調用 latch.await() 方法,當前線程會立刻處於類似sleep的狀態,直到同步計數器減爲0。也就是說, latch.await() 方法後面的代碼不會被執行,直到同步計數器減爲0。
(4)CountDownLatch 機制不是用來保護共享資源或者臨界區。它是用來同步一個或者多個線程。它只能使用一次。也就是說,一旦CountDownLatch的計數器到達0,任何對它的方法的調用都是無效的。如果你想再次同步,你必須創建新的對象。

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