《 Effecit In Java 》說過,從java 1.5發現版本開始, 就不建議使用wait和notify,它們使用比較困難,可以使用更高階併發工具來替代。

圖一所說的同步器是指那些能使執行緒等待另一個執行緒的物件,常用的有cyclicBarrier和倒計數鎖存器CountDownLatch和semaphore。

CountDownLatch

一個同步輔助類,在完成一組正在其他執行緒中執行的操作之前,它允許一個或多個執行緒一直等待。它的倒計數類似於AutomicInteger的getAndDecrement()。但它還有另一個主要作用類似於 wait和notify。

程式碼示例

package com.bbk.u001.handle;

import java.util.concurrent.CountDownLatch;

import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component; /**
* CountDownLatch的使用
* @ClassName: StatsSimilarKnowledgeHandle
* @Description: TODO
* @author wasim
* @create at 2015-8-12 下午8:44:51
*
*/
@Component
public class CountDownLatchHandle { @Autowired
ThreadPoolTaskExecutor executor; @PostConstruct
public void handleStatsQuestionKnowledge(){ CountDownLatch startSignal = new CountDownLatch(12); //匯出檔案
executor.execute(new ExportStats(startSignal)); //匯出檔案前,需要先迴圈下面12個執行緒
for(int i=0;i<12;i++){
executor.execute(new similarKnowledgeHandle(startSignal));
} } public class similarKnowledgeHandle implements Runnable{
CountDownLatch startSignal; public similarKnowledgeHandle(CountDownLatch startSignal) {
this.startSignal =startSignal;
} @Override
public void run() {
startSignal.countDown();
System.out.println(startSignal.getCount()); //顯示當前計數
}
} public class ExportStats implements Runnable{ CountDownLatch startSignal; public ExportStats(CountDownLatch startSignal) {
this.startSignal =startSignal;
} @Override
public void run() {
try {
startSignal.await(); //當計數為0前,匯出檔案的執行緒一直處於等待狀態
System.out.println("start export.......");
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
}

cyclicBarrier

一個同步輔助類,它允許一組執行緒互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的執行緒的程式中,這些執行緒必須不時地互相等待,此時 CyclicBarrier 很有用。因為該 barrier 在釋放等待執行緒後可以重用,所以稱它為迴圈 的 barrier。

程式碼示例:

class Solver {
final int N;
final float[][] data;
final CyclicBarrier barrier; class Worker implements Runnable {
int myRow;
Worker(int row) { myRow = row; }
public void run() {
while (!done()) {
processRow(myRow); try {
barrier.await();
} catch (InterruptedException ex) {
return;
} catch (BrokenBarrierException ex) {
return;
}
}
}
} public Solver(float[][] matrix) {
data = matrix;
N = matrix.length;
barrier = new CyclicBarrier(N,
new Runnable() {
public void run() {
mergeRows(...);
}
});
for (int i = 0; i < N; ++i)
new Thread(new Worker(i)).start(); waitUntilDone();
}
}

cyclicBarrier 和 CountDownLatch 的區別