Java之CountDownLatch ---控制線程執行順序


一,類介紹

這是java.util.concurrent包里的一個同步輔助類,它有兩個主要的常用方法  countDown()方法以及await()方法。在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。

這個類可以幫助我們做什么事呢?

二,實例運行

列舉一個場景,三個人賽跑,哨聲一響同時出發,跑到一半時A選手突然覺得拿名次沒什么意思,當最后一名也挺好,然后他就讓B,C先跑到終點,然后自己再跑。

這里我們可以開三個線程模擬三位選手,看看我們怎么通過這兩個重要方法來實現A選手的想法的。

代碼如下,不妨先復制一下,跑起來再說。

public class Sample {

        /**
         * 計數器,用來控制線程
         * 傳入參數2,表示計數器計數為2
         */
        private final static CountDownLatch mCountDownLatch = new CountDownLatch(2);
        
        /**
         * A線程類
         */
        private static class ThreadA extends Thread {
            
            @Override
            public void run() {
                System.out.println("A選手  出發!");
                try {
                    // 會阻塞在這里等待 mCountDownLatch 里的count變為0;
                    // 也就是等待另外的WorkingThread調用countDown()
                    mCountDownLatch.await();
                } catch (InterruptedException e) {
                    
                }
                System.out.println("A選手  到終點拉!");
            }
        }
        
        /**
         * BC線程類
         */
        private static class WorkingThread extends Thread {
            private final String mThreadName;
            private final int mSleepTime;
            public WorkingThread(String name, int sleepTime) {
                mThreadName = name;
                mSleepTime = sleepTime;
            }
            
            @Override
            
            public void run() {
                System.out.println("[" + mThreadName + "] 出發!");
                try {  
                        Thread.sleep(mSleepTime);  
                } catch (InterruptedException e) {  
                        e.printStackTrace();  
                }
         
                System.out.println("[" + mThreadName + "] 到終點拉!"); 
                mCountDownLatch.countDown();
            }
        }
        
        public static void main(String[] args) throws Exception {
            // 最先run ThreadA
            new ThreadA().start();
            
            new WorkingThread("B選手", 2000).start();
         
            new WorkingThread("C選手", 2000).start();
       
        }
    
}

 

三,代碼分析

現在我們來分析一下代碼,我們先開啟了A線程,它先跑了,但是在A線程的run方法中,調用了await()方法,這個方法可以讓當前線程處於等待狀態,直到計數器為0時,才繼續往下執行。

好了計數器是什么東西,其實CountDownLatch這個類我們就可以把它看出一個計數器,實際上它內部也真實維護了一個count計數,對計數的操作都是原子的,啰嗦一句,原子操作的意思

就是當一個線程對count進行修改時,其他的線程是不可以同時修改的。上面說到要等到計數器為0才行,顯然想讓它為0,就得有個初始值,然后再有減的操作才行吧。賦初始值的操作,就是new這

個對象的時候就完成拉,代碼中 new CountDownLatch(2) 就是給count設為2的操作,然后mCountDownLatch.countDown()這個方法就是count減去1的操作,代碼我們減了兩次,為0之后,A選手才繼續跑完。

 

好了,這樣的栗子好像只能幫助理解,但是挑不起興趣,再舉一個工作中真實用到的場景。

開啟多個線程分塊下載一個大文件,每個線程只下載固定的一截,最后由另外一個線程來拼接所有的分段,那么這時候我們可以考慮使用CountDownLatch來控制並發,使得拼接的線程放在最后執行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM