1. 程式人生 > >Java多執行緒與併發庫高階應用之倒計時計數器CountDownLatch

Java多執行緒與併發庫高階應用之倒計時計數器CountDownLatch

CountDownLatch類是一個倒計時計數器,在完成一組正在其他執行緒中執行的操作之前,它允許一個或多個執行緒一直等待。用給定的計數初始化 CountDownLatch。由於呼叫了countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。之後,會釋放所有等待的執行緒,await 的所有後續呼叫都將立即返回。

CountDownLatch 是一個通用同步工具,它有很多用途。將計數1初始化的 CountDownLatch 用作一個簡單的開/關鎖存器,或入口:在通過呼叫 countDown() 的執行緒開啟入口前,所有呼叫 await 的執行緒都一直在入口處等待。用N初始化的 CountDownLatch 可以使一個執行緒在N個執行緒完成某項操作之前一直等待,或者使其在某項操作完成N次之前一直等待。

CountDownLatch猶如比賽的發令官,多條執行緒猶如運動員。倒計時到零時一聲槍響,運動員開始比賽,即多條執行緒開始執行。

使用CountDownLatch很簡單,因為它只提供了一個構造器:

CountDownLatch(int count):構造一個用給定計數初始化的CountDownLatch。

線上程中呼叫CountDownLatch物件的await()方法,會使當前執行緒在鎖存器倒計數至零之前一直等待,除非執行緒被中斷。而呼叫countDown()方法會遞減鎖存器的計數,如果計數到達零,則釋放所有等待的執行緒。

見下面程式:啟動三個執行緒等待主執行緒釋出命令,主執行緒釋出命令後等待三個執行緒執行完後的反饋。

public class CountDownLatchDemo {

	public static void main(String[] args) {
		
		//執行緒池
		ExecutorService pool = Executors.newCachedThreadPool();
		//定義兩個倒計時計數器
		//等待命令倒計時計數器
		final CountDownLatch countOrder = new CountDownLatch(1);
		//等待反饋倒計時計數器
		final CountDownLatch countAnswer = new CountDownLatch(3);
		
		//3個子執行緒
		for(int i = 0; i < 3; i++){
			Runnable target = new Runnable() {
				@Override
				public void run() {
					try {
						System.out.println(Thread.currentThread().getName() + 
								"-等待命令");
						//等待countOrder為0時停止等待,向下執行
						countOrder.await();
						
						System.out.println(Thread.currentThread().getName() + 
								"-得到命令,開始執行");
						Thread.sleep((long)(Math.random()*10000));
						System.out.println(Thread.currentThread().getName() + 
								"-命令執行完成,迴應結果");
						//將countAnswer減一
						countAnswer.countDown();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
				}
			};
			pool.execute(target);
		}
		
		//主執行緒
		try{
			Thread.sleep((long)(Math.random()*10000));
			System.out.println(Thread.currentThread().getName() + 
					"-即將釋出命令");
			//將countOrder減一
			countOrder.countDown();
			System.out.println(Thread.currentThread().getName() + 
					"-已釋出命令,等待迴應");
			//等待迴應
			countAnswer.await();
			System.out.println(Thread.currentThread().getName() + 
					"-已收到所有迴應結果");
		}catch(InterruptedException e) {
			e.printStackTrace();
		}
		
		pool.shutdown();
	}

}


執行程式

看到3個子執行緒在接到主執行緒命令前都等待,當主執行緒呼叫了countDown() 方法後減為零,3個子執行緒開始執行,並且主執行緒等待子執行緒執行完後的迴應。3個子執行緒沒執行完一個呼叫countDown() 方法,當3個都執行完後,主執行緒收到迴應。