1. 程式人生 > >Java併發程式設計(二) CountDownLatch

Java併發程式設計(二) CountDownLatch

接上一回,如果4個工人在裝配車輪時,工作間中沒有車輪可裝配,工人必須等到車輪運送到工作間合適的位置後才可以進行裝配車輪的工作。所以,在Worker類中加入一把新的CountDownLatch-----tyreReadyLatch,

讓這把鎖告訴Worker執行緒,在輪胎到來之前,必須處於等待狀態,假如不等待的話,這個Worker執行緒會跑出錯誤,導致的結果是這輛車裝配輪胎整個任務失敗。所以必須呼叫

tyreReadyLatch.await();

這個語句確保Worker執行緒在等待輪胎的到來。

BlockingQueue來模擬當前工作間中放輪胎的位置。假設能放下4個輪胎。往這個Queue中放入4個輪胎,運送輪胎的工作在main函式中完成

for (int i = 0; i < 4; i++){
	tyries.offer(new Tyre(i));
	Thread.sleep(500);
}

OK,4個輪胎就位後,呼叫下面這個語句,釋放tyreReadyLatch,初始化時,tyreReadyLatch鎖的計數器被設定為1,所以只需要呼叫一次tyreReadyCount的countDown()方法。以告訴4個Worker執行緒,你們可以進行輪胎的裝配工作。

tyreReadyLatch.countDown();

下面的這行程式碼模擬Worker執行緒在接受到可以進行裝配工作的“指令”後,從工作間裡拿出一個輪胎。

Tyre tyre = tyries.take();

拿到輪胎後,Worker執行緒的工作模式和第一回中的工人裝配輪胎一節中的行為是一樣的了。

可見,使用多個CountDownLatch可以比較精確的控制一個執行緒的執行狀態。CountDownLatch的await和countDown方法必須配合使用。否則會造成執行緒一直處於等待狀態。

最後,完整的程式碼清單。

public class Worker implements Runnable {
	private String name;
	static CountDownLatch workDoneLatch = new CountDownLatch(4);
	static CountDownLatch tyreReadyLatch = new CountDownLatch(1);
	static ArrayBlockingQueue<Tyre> tyries = new ArrayBlockingQueue<Tyre>(4);

	public Worker(String name) {
		this.name = name;
	}

	@Override
	public void run() {
		try {
			System.out.format("%s is waiting for tyre ready....%n", name);
			tyreReadyLatch.await();
			Tyre tyre = tyries.take();
			System.out.format("%s is assembling.%n", tyre);
			marshalTyre();
			System.out.format("%s is assembled.%n", tyre);
			workDoneLatch.countDown();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	private void marshalTyre() throws InterruptedException {
		Thread.sleep(new Random().nextInt(60000));
	}

	/**
	 * @param args
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws InterruptedException {

		ExecutorService executorService = Executors.newFixedThreadPool(4);
		long s = System.currentTimeMillis();
		String works[] = { "John Chembers", "Bill Gates", "Larry Page", "Ericsson Limited" };
		for (int i = 0; i < 4; i++)
			executorService.execute(new Worker(works[i]));

		for (int i = 0; i < 4; i++){
			tyries.offer(new Tyre(i));
			Thread.sleep(500);
		}
		tyreReadyLatch.countDown();

		workDoneLatch.await();
		System.out.format("the 4 tyres were assembled. costs %d ms.%n", System.currentTimeMillis() - s);
		executorService.shutdown();
	}
}

輔助類Tyre,代表輪胎

class Tyre {

	private int id;

	public Tyre(int id) {
		this.id = id;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return "Tyre: " + id;
	}
}
 

[原創內容,版權所有,如有轉載,請註明出處,如有錯誤之處,請指出,不勝感激]