java.util.concurrent 中的CyclicBarrier用于多线程测试
在实际应用中,有时候需要多个线程同时工作以完成同一件事情,而且在完成过程中,往往会等待其他线程都完成某一阶段后再执行,等所有线程都到达某一个阶段后再统一执行。
比如有几个旅行团需要途经深圳、广州、韶关、长沙最后到达武汉。旅行团中有自驾游的,有徒步的,有乘坐旅游大巴的;这些旅行团同时出发,并且每到一个目的地,都要等待其他旅行团到达此地后再同时出发,直到都到达终点站武汉。
这时候CyclicBarrier就可以派上用场。CyclicBarrier最重要的属性就是参与者个数,另外最要方法是await()。当所有线程都调用了await()后,就表示这些线程都可以继续执行,否则就会等待。
比如有几个旅行团需要途经深圳、广州、韶关、长沙最后到达武汉。旅行团中有自驾游的,有徒步的,有乘坐旅游大巴的;这些旅行团同时出发,并且每到一个目的地,都要等待其他旅行团到达此地后再同时出发,直到都到达终点站武汉。
这时候CyclicBarrier就可以派上用场。CyclicBarrier最重要的属性就是参与者个数,另外最要方法是await()。当所有线程都调用了await()后,就表示这些线程都可以继续执行,否则就会等待。
计数类
package test.multithread;
public class Counter {
private int counter;
public void increment(){
counter++;
}
public int value(){
return counter;
}
}
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);
}
}
}
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());
}
}
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());
}
}