在實際應用中,有時候需要多個線程同時工作以完成同一件事情,而且在完成過程中,往往會等待其他線程都完成某一階段後再執行,等所有線程都到達某一個階段後再統一執行。
比如有幾個旅行團需要途經深圳、廣州、韶關、長沙最後到達武漢。旅行團中有自駕遊的,有徒步的,有乘坐旅遊大巴的;這些旅行團同時出發,並且每到一個目的地,都要等待其他旅行團到達此地後再同時出發,直到都到達終點站武漢。
這時候CyclicBarrier就可以派上用場。CyclicBarrier最重要的屬性就是參與者個數,另外最要方法是await()。當所有線程都調用了await()後,就表示這些線程都可以繼續執行,否則就會等待。
計數類
package test.multithread;
public class Counter {
private int counter;
public void increment(){
counter++;
}
public int value(){
return counter;
}
}
自訂線程類
package test.multithread;
import java.util.concurrent.CyclicBarrier;
public class SynchedThread extends Thread{
private CyclicBarrier enterBarrier;
private CyclicBarrier exitBarrier;
public SynchedThread(Runnable runnable,
CyclicBarrier enterBarrier,
CyclicBarrier exitBarrier){
super(runnable);
this.enterBarrier = enterBarrier;
this.exitBarrier = exitBarrier;
}
@Override
public void run(){
try{
enterBarrier.await();
super.run();
exitBarrier.await();
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
測試類別
package test.multithread;
import static org.junit.Assert.assertEquals;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import org.junit.Test;
public class MultiThreadTest {
@Test
public void testAAA() throws Exception{
final Counter counter = new Counter();
final int numberOfThreads = 20;
final int incrementsPerThread = 1000;
CyclicBarrier entryBarrier = new CyclicBarrier(numberOfThreads + 1);
CyclicBarrier exitBarrier = new CyclicBarrier(numberOfThreads + 1);
Runnable runnable = new Runnable(){
public void run(){
for(int i=0; i < incrementsPerThread; i++){
counter.increment();
}
}
};
for(int i=0; i < numberOfThreads; i++){
new SynchedThread(runnable, entryBarrier, exitBarrier).start();
}
assertEquals(0, counter.value());
entryBarrier.await();
exitBarrier.await();
assertEquals(numberOfThreads * incrementsPerThread, counter.value());
}
}