CountDownLatch使用

1、類介紹

一個同步輔助類,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。用給定的計數 初始化 CountDownLatch。由於調用了 countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。之後,會釋放所有等待的線程,await 的所有後續調用都將立即返回。這種現象只出現一次——計數無法被重置。 一個線程(或者多個), 等待另外N個線程完成某個事情之後才能執行。

      不僅可以阻塞子線程,同時還可以阻塞主線程。

2、使用場景

       在一些應用場合中,需要等待某個條件達到要求後才能做後面的事情;同時當線程都完成後也會觸發事件,以便進行後面的操作。 這個時候就可以使用CountDownLatch。CountDownLatch最重要的方法是countDown()和await(),前者主要是倒數一次,後者是等待倒數到0,如果沒有到達0,就只有阻塞等待了。

3、方法說明


countDown

public void countDown()

    遞減鎖存器的計數,如果計數到達零,則釋放所有等待的線程。如果當前計數大於零,則將計數減少。如果新的計數爲零,出於線程調度目的,將重新啓用所有的等待線程。

    如果當前計數等於零,則不發生任何操作。

await

public boolean await(long timeout,
                     TimeUnit unit)
              throws InterruptedException

    使當前線程在鎖存器倒計數至零之前一直等待,除非線程被中斷或超出了指定的等待時間。如果當前計數爲零,則此方法立刻返回 true 值。

    如果當前計數大於零,則出於線程調度目的,將禁用當前線程,且在發生以下三種情況之一前,該線程將一直處於休眠狀態:

        由於調用 countDown() 方法,計數到達零;或者
        其他某個線程中斷當前線程;或者
        已超出指定的等待時間。

    如果計數到達零,則該方法返回 true 值。

    如果當前線程:

        在進入此方法時已經設置了該線程的中斷狀態;或者
        在等待時被中斷,

    則拋出 InterruptedException,並且清除當前線程的已中斷狀態。如果超出了指定的等待時間,則返回值爲 false。如果該時間小於等於零,則此方法根本不會等待。

     

    參數:
        timeout - 要等待的最長時間
        unit - timeout 參數的時間單位。
    返回:
        如果計數到達零,則返回 true;如果在計數到達零之前超過了等待時間,則返回 false
    拋出:
        InterruptedException - 如果當前線程在等待時被中斷


4、相關實例一


public class CountDownLatchTest {

    // 模擬了100米賽跑,10名選手已經準備就緒,只等裁判一聲令下。當所有人都到達終點時,比賽結束。
    public static void main(String[] args) throws InterruptedException {

        // 開始的倒數鎖 
        final CountDownLatch begin = new CountDownLatch(1);  

        // 結束的倒數鎖 
        final CountDownLatch end = new CountDownLatch(10);  

        // 十名選手 
        final ExecutorService exec = Executors.newFixedThreadPool(10);  

        for (int index = 0; index < 10; index++) {
            final int NO = index + 1;  
            Runnable run = new Runnable() {
                public void run() {  
                    try {  
                        // 如果當前計數爲零,則此方法立即返回。
                        // 等待
                        begin.await();  
                        Thread.sleep((long) (Math.random() * 10000));  
                        System.out.println("No." + NO + " arrived");  
                    } catch (InterruptedException e) {  
                    } finally {  
                        // 每個選手到達終點時,end就減一
                        end.countDown();
                    }  
                }  
            };  
            exec.submit(run);
        }  
        System.out.println("Game Start");  
        // begin減一,開始遊戲
        begin.countDown();  
        // 等待end變爲0,即所有選手到達終點
        end.await();  
        System.out.println("Game Over");  
        exec.shutdown();  
    }
}

輸出結果:

Game Start
No.10 arrived
No.5 arrived
No.2 arrived
No.4 arrived
No.7 arrived
No.3 arrived
No.1 arrived
No.8 arrived
No.6 arrived
No.9 arrived
Game Over

5、相關實例二

public class CountDownLatchDemo {
	final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static void main(String[] args) throws InterruptedException {
    	CountDownLatch latch=new CountDownLatch(2);//兩個工人的協作
    	Worker worker1=new Worker("zhang san", 5000, latch);
    	Worker worker2=new Worker("li si", 8000, latch);
    	worker1.start();//
    	worker2.start();//
    	latch.await();//等待所有工人完成工作
        System.out.println("all work done at "+sdf.format(new Date()));
	}
    
    
    static class Worker extends Thread{
    	String workerName; 
    	int workTime;
    	CountDownLatch latch;
    	public Worker(String workerName ,int workTime ,CountDownLatch latch){
    		 this.workerName=workerName;
    		 this.workTime=workTime;
    		 this.latch=latch;
    	}
    	public void run(){
    		System.out.println("Worker "+workerName+" do work begin at "+sdf.format(new Date()));
    		doWork();//工作了
    		System.out.println("Worker "+workerName+" do work complete at "+sdf.format(new Date()));
    		latch.countDown();//工人完成工作,計數器減一

    	}
    	
    	private void doWork(){
    		try {
				Thread.sleep(workTime);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
    	}
    }
	     
}

輸出結果:

Worker li si do work begin at 2015-03-11 16:25:10
Worker zhang san do work begin at 2015-03-11 16:25:10
Worker zhang san do work complete at 2015-03-11 16:25:15
Worker li si do work complete at 2015-03-11 16:25:18
all work done at 2015-03-11 16:25:18

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