1. 程式人生 > >多執行緒之CountDownLatch & CyclicBarrier

多執行緒之CountDownLatch & CyclicBarrier

CountDownLatch 俗稱閉鎖 建構函式中可以傳遞一個count 非負的整數值的數字,表示計數值,當這個計數值減到為0時,才能繼續執行,比如說計算幾個執行緒執行消耗時間 。CyclicBarrier 俗稱同步屏障,它的建構函式有兩種,其他一個也是傳遞一個非負的整數值,表示幾個執行緒需要達到屏障處,另一個建構函式除了那個非零的整數值,還可以傳遞一個Runnable介面的引數,可以在都達到屏障處後在執行一個Runnable介面的實現。旨在所有的執行緒都達到了一個屏障的時候,再執行後續的操作。已計算執行緒的執行時間來說,我們可以嘗試用CountDownLatch,CyclicBarrier及join來試試看。

public class TestCountDownLatchAndCyclicBarrier {
	
	public static void main(String[] args) {
		
		CountDownLatch cdl = new CountDownLatch(3);
		TwoUseDemo ldtest = new TwoUseDemo(cdl);
		Instant start_0 = Instant.now();
		for(int i = 0;i<3;i++){
			new Thread(()->ldtest.testCountDownLatch(),"ldtest_"+i).start();
		}
		try {
			cdl.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+" 耗費時間為>>>>>>>>"+Duration.between(start_0, Instant.now()));
		
		Instant start_1 = Instant.now();
		CyclicBarrier cb = new CyclicBarrier(3, new Runnable() {
			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName()+" 耗費時間>>>>>>>>"+Duration.between(start_1, Instant.now()));
			}
		});
		TwoUseDemo cbtest = new TwoUseDemo(cb);
		for(int i = 0;i<3;i++){
			new Thread(()->cbtest.testCyclicBarrier(),"cbtest_"+i).start();
		}
		
		TwoUseDemo blankTest = new TwoUseDemo();
		Instant start_2 = Instant.now();
		List<Thread> threads = new ArrayList<>();
		
		IntStream.range(0, 3).forEach((i)->{
			threads.add(new Thread(()->{
				blankTest.blank();
			},"blank_"+i));
		});
		threads.stream().forEach((t)->{
			t.start();
			try {
				t.join();
			} catch (Exception e) {
				e.printStackTrace();
			}
		});
		System.out.println(Thread.currentThread().getName()+" 耗費時間為>>>>>>>>"+Duration.between(start_2, Instant.now()));
	}
}

class TwoUseDemo{
	
	private CountDownLatch latch;
	
	private CyclicBarrier cb;
	
	public TwoUseDemo(){
		
	}
	
	public TwoUseDemo(CountDownLatch latch){
		this.latch = latch;
	}
	
	public TwoUseDemo(CyclicBarrier cb){
		this.cb = cb;
	}
	
	public void testCountDownLatch(){
		for(int i = 0;i<6;i++){
			if(i%2==0){
				System.out.println(Thread.currentThread().getName()+">>>>>>>>>>>>>>>"+i);
			}
		}
		latch.countDown();
	}
	
	public void testCyclicBarrier(){
		for(int i = 0;i<6;i++){
			if(i%2==0){
				System.out.println(Thread.currentThread().getName()+">>>>>>>>>>>>>>>"+i);
			}
		}
		try {
			cb.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (BrokenBarrierException e) {
			e.printStackTrace();
		}
	}
	
	public void blank(){
		for(int i = 0;i<6;i++){
			if(i%2==0){
				System.out.println(Thread.currentThread().getName()+">>>>>>>>>>>>>>>"+i);
			}
		}
	}
}

控制檯執行結果如下



有點特別的地方是 CyclicBarrier 中的最後執行Runnable的執行緒是從原先屏障處等待的幾個執行緒中選擇了一個來執行。