Javaスレッド学習ノート(10)CountDownLatchとCyclicBarrier

6493 ワード

CountDownLatch :
他のスレッドで実行されている一連の操作を完了する前に、1つ以上のスレッドを待機させる同期支援クラス.与えられたカウントでCountDownLatchを初期化します.countDown()メソッドが呼び出されるため、現在のカウントがゼロに達するまでawaitメソッドはブロックされます.その後、待機しているすべてのスレッドが解放され、awaitの後続呼び出しはすぐに返されます.この現象は1回しか現れません.カウントはリセットできません.
 
CountDownLatchは、1つのタスクをn個の独立した部分に分けるのに適しており、これらの部分が完了してから次のタスクを継続すると、CountDownLatchは1回しか出発できず、カウント値はリセットできません.
CyclicBarrier:
共通のバリアポイント(common barrier point)に達するまでスレッドのセットを互いに待つことができる同期支援クラス.一定サイズのスレッドのセットに関連するプログラムでは、これらのスレッドは常に互いに待たなければならない.この場合、CyclicBarrierは有用である.このbarrierは、待機スレッドを解放した後に再利用できるため、ループのbarrierと呼ばれる.
CyclicBarrierは複数回繰り返し使用できます
 
次の2つの例を示します.1つはCountDownLatchベースのシミュレーションプロジェクトで、1つのプロジェクトは複数のモジュールに分けることができますが、これらのモジュールが完了してから次の作業を継続することができます.
一つはCyclicBarrierに基づくリレーシミュレーションで、4人の選手が走り終わった後に最終成績を報告した.
 
 
package com.woxiaoe.study.thread;

import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 *        ,           ,     
 *          
 * @author  e
 *
 * 2010-4-30   07:41:37
 */
class Module implements Runnable{
	private CountDownLatch latch;
	private String moduleName;
	private int time;//  
	
	

	public Module(CountDownLatch latch, String moduleName,int time) {
		super();
		this.latch = latch;
		this.moduleName = moduleName;
		this.time = time;
	}



	@Override
	public void run() {
		try {
			work();
			latch.countDown();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	private void work() throws InterruptedException{
		TimeUnit.MILLISECONDS.sleep(time);
		System.out.println(moduleName + "   ,  :" + time);
	}
}
class Controller implements Runnable{
	private CountDownLatch latch;

	public Controller(CountDownLatch latch) {
		super();
		this.latch = latch;
	}

	@Override
	public void run() {
		try {
			latch.await();
			System.out.println("       ,    ");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
}
public class Project {
	static final int SIZE = 20;
	public static void main(String[] args) {
		CountDownLatch latch = new CountDownLatch(SIZE);
		Random r = new Random();
		ExecutorService exec = Executors.newCachedThreadPool();
		Controller controller = new Controller(latch);
		exec.execute(controller);
		for(int i = 0; i < SIZE; i++){
			exec.execute(new Module(latch, "  " + (i + 1), r.nextInt(2000)));
		}
		
		exec.shutdown();
		
	}

}

 
 Output:
モジュール4完成、消耗時間:108モジュール10完成、消耗時間:123モジュール7完成、消耗時間:136モジュール19完成、消耗時間:235モジュール5完成、消耗時間:475モジュール11完成、消耗時間:653モジュール1完成、消耗時間:745モジュール2完成、消耗時間:826モジュール20完成、消耗時間:1030モジュール16完成、消耗時間:1151モジュール3完成、消耗時間:1204モジュール15完成、消耗時間:1219モジュール13完成、消耗時間:1274モジュール17完成、消耗時間:1337モジュール8完成、消耗時間:1366モジュール6完成、消耗時間:1491モジュール14完成、消耗時間:1739モジュール18完成、消耗時間:1766モジュール12完成、消耗時間:1883モジュール9完成、消耗時間:1951所有モジュール全部完成、任務完成
 
package com.woxiaoe.study.thread;

import java.util.Random;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 *  java  4X100   
 *         ,  CyclicBarrier
 * @author  e
 *
 * 2010-4-30   08:13:40
 */
class Player implements Runnable{
	private String name;
	private CyclicBarrier barrier;
	private Player next;//   
	private int time;//  
	private boolean run;//   
	public Player(String name, CyclicBarrier barrier, boolean run) {
		super();
		this.name = name;
		this.barrier = barrier;
		this.run = run;
	}
	@Override
	public void run() {
		try {
			synchronized (this) {
				while(!run){//    
					wait();
				}
			}
			Random r = new Random();
			TimeUnit.MILLISECONDS.sleep(r.nextInt(2000));
			next(next,11 + r.nextInt(2));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
	private void next(Player next, int time) {
		System.out.println(name + "   :" + time + ",   ");
		if(next != null){
			next.setTime(this.time + time);
			synchronized (next) {
				next.setRun(true);
				next.notify();
			}
		}else{
			System.out.println("  ,   :" + (this.time + time));
		}
	}
	public void setTime(int time) {
		this.time = time;
	}
	public int getTime(){
		return this.time;
	}
	public void setNext(Player next) {
		this.next = next;
	}
	public void setRun(boolean run) {
		this.run = run;
	}
	
}
public class RelayRace {
	
	public static void main(String[] args) throws InterruptedException {
		final Player[] players = new Player[4];
		ExecutorService exec = Executors.newCachedThreadPool();
		CyclicBarrier barrier = new CyclicBarrier(4, new Runnable() {
			
			@Override
			public void run() {
				System.out.println("  ,   :" + players[3].getTime());
			}
		});
		for(int i = 0; i < 4; i++){
			players[i] = new Player("  " + ( i + 1), barrier, i == 0);
		}
		for(int i = 0; i < 4; i++){
			if( i < 3){
				players[i].setNext(players[i + 1]);
				exec.execute(players[i]);
			}else{
				exec.execute(players[3]);
				break;
			}
		}
		/*TimeUnit.SECONDS.sleep(3);
		 * CyclicBarrier     
		for(int i = 0; i < 4; i++){
			if( i < 3){
				players[i].setNext(players[i + 1]);
				exec.execute(players[i]);
			}else{
				exec.execute(players[3]);
				break;
			}
		}*/
	}

}

 Output:
队员1用时:11,バトンタッチ队员2用时:11,バトンタッチ队员3用时:11,バトンタッチ队员4用时:12,バトンタッチ棒走り终わり,総用时:45