Java中的 CyclicBarrier详解
1. 什么是CyclicBarrier
CyclicBarrier是Java并发包中的一个类,可以让一组线程在某个条件达成时全部同时开始执行。简而言之,CyclicBarrier是一种同步机制,它允许指定的线程等待彼此到达某个同步点。
CyclicBarrier和CountDownLatch都可以用于线程间的同步,但它们之间也存在一些区别。CountDownLatch是一种能够使一个或多个线程等待一系列指定的任务执行完后再执行的同步机制,而CyclicBarrier是一种等待所有线程都满足某个条件后再继续执行的同步机制。
CyclicBarrier的用法非常简单,只需要在创建实例时指定同步点即可,线程在运行过程中到达同步点时将被阻塞,直到所有线程都到达同步点后才会一起继续执行。
2. CyclicBarrier常用方法
CyclicBarrier类提供了一些方法可以用于实现线程间的同步控制。
2.1 构造方法
CyclicBarrier的构造方法有两种基本形式:
public CyclicBarrier(int parties)
构造一个新的CyclicBarrier,它将在指定数量的线程(称为parties)等待之后启动执行。
public CyclicBarrier(int parties, Runnable barrierAction)
构造一个新的CyclicBarrier,它将在指定数量的线程等待之后启动执行,并会执行指定的Runnable。
2.2 await()
CyclicBarrier的唯一方法是await(),调用await()表示该线程已经到达了同步点。当某个线程调用await()时,它将会被阻塞,而其他线程继续执行,直到所有线程都到达了同步点。
public void await() throws InterruptedException, BrokenBarrierException;
2.3 reset()
CyclicBarrier还提供了reset()方法,用于重置同步点。在调用reset()方法后,所有已经在等待的线程都将抛出BrokenBarrierException异常。
public void reset();
3. CyclicBarrier的使用示例
下面的示例演示了如何使用CyclicBarrier来实现一批线程同时开始执行:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(5, new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is working");
}
});
for (int i = 0; i < 5; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " is waiting");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is working");
}
}, "Thread-" + i).start();
}
}
}
运行结果如下:
Thread-2 is waiting
Thread-3 is waiting
Thread-4 is waiting
Thread-0 is waiting
Thread-1 is waiting
Thread-2 is working
Thread-3 is working
Thread-4 is working
Thread-0 is working
Thread-1 is working
上面的代码中,我们创建了一个CyclicBarrier实例,其参数parties为5,表示要等待5个任务完成。在每一个线程中,我们先打印出当前线程正在等待,然后调用cyclicBarrier.await()方法将线程阻塞。当所有线程都到达了同步点后,会执行CyclicBarrier的构造方法中指定的Runnable,同时所有被阻塞的线程开始同步执行,打印出"Thread-x is working",x为线程的编号。
另一个示例演示了如何使用CyclicBarrier来模拟比赛的开始、进行和结束,其中比赛有三个阶段:准备、开始、结束。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class RaceDemo {
private static CyclicBarrier cyclicBarrier;
public static void main(String[] args) throws InterruptedException {
cyclicBarrier = new CyclicBarrier(4, new Runnable() {
@Override
public void run() {
System.out.println("All the players are ready, let's start the game!");
}
});
Player player1 = new Player("Tom");
Player player2 = new Player("Jerry");
Player player3 = new Player("Mike");
Player player4 = new Player("John");
player1.start();
player2.start();
player3.start();
player4.start();
player1.join();
player2.join();
player3.join();
player4.join();
}
static class Player extends Thread {
private String name;
public Player(String name) {
this.name = name;
}
@Override
public void run() {
try {
System.out.println(name + " is preparing...");
Thread.sleep(1000);
cyclicBarrier.await();
System.out.println(name + " starts running...");
Thread.sleep(3000);
cyclicBarrier.await();
System.out.println(name + " is close to the finish line...");
Thread.sleep(2000);
cyclicBarrier.await();
System.out.println(name + " crosses the finish line!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
运行结果如下:
Tom is preparing...
Jerry is preparing...
Mike is preparing...
John is preparing...
All the players are ready, let's start the game!
Tom starts running...
Mike starts running...
Jerry starts running...
John starts running...
Jerry is close to the finish line...
Mike is close to the finish line...
Tom is close to the finish line...
John is close to the finish line...
Jerry crosses the finish line!
Mike crosses the finish line!
Tom crosses the finish line!
John crosses the finish line!
上面的代码中,我们创建了一个CyclicBarrier实例,其参数parties为4,表示等待4个运动员准备就绪后开始比赛。在每一个运动员中,我们通过cyclicBarrier.await()将每一个运动员线程阻塞,直到所有运动员都到达同步点。当所有运动员都准备就绪后,CyclicBarrier的构造方法中指定的Runnable开始执行,打印出"All the players are ready, let's start the game!",同时所有阻塞的线程开始继续执行比赛流程。当每一阶段都完成后,所有线程再次被阻塞,等待其他线程完成当前阶段。最后一阶段完成后,所有线程将一起结束比赛。
通过这两个示例,我们可以看到CyclicBarrier的强大功能和使用方法,它可以方便地实现线程之间的同步控制,很好地提高了并发编程的效率。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中的 CyclicBarrier详解 - Python技术站