Series of concurrent tools:
Java Concurrency utility class (locking CountDownLatch)
Java Concurrency utility classes (CyclicBarrier)
Java Concurrency Utility class (Semaphore)
A CyclicBarrier is suitable for situations where you want to create a set of tasks that perform work in parallel and then wait until all the tasks are complete before the next step. The key difference between a fence and a lock is that all threads must reach the fence at the same time in order to continue execution.
Latches are used to wait for events, while fences are threads waiting for each other to decide what to do next when they both arrive. See the Java concurrency utility class (CountDownLatch)
Take the case of the athletes, who run to the finish line and wait for each other to finish before they drink together. (The runners may not be allowed to drink. Maybe we’ll run another round.)
Here’s an example of a horse racing program:
package concurrency; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.*; class Horse implements Runnable { private static int counter = 0; private final int id = counter++; private int strides = 0; private static Random rand = new Random(47); private static CyclicBarrier barrier; public Horse(CyclicBarrier b) {barrier = b; } public synchronized intgetStrides() {returnstrides; } public voidrun() {
try {
while(! Synchronized (this) {strides += rand. NextInt (3); // take 0,1 or 2 steps} barrier. Await (); // When all the other horses have finished, } catch (InterruptedException e) {} Catch (BrokenBarrierException e) {throw new RuntimeException(e); } } @Override public StringtoString() {
return "Horse " + id + "";
}
public String tracks() {
StringBuilder s =new StringBuilder();
for(int i = 0; i < getStrides(); i++) s.append("*"); // here prints the track of each horse.return s.toString();
}
}
public class HorseRace {
static final int FINISH_LINE = 75;
private List<Horse> horses = new ArrayList<Horse>();
private ExecutorService exec = Executors.newCachedThreadPool();
private CyclicBarrier barrier;
public HorseRace(int nHorses, final int pause) {
barrier = new CyclicBarrier(nHorses, new Runnable() {
@Override
public void run() {
StringBuilder s = new StringBuilder();
for (int i = 0; i < FINISH_LINE; i++) {
s.append("="); } system.out.println (s);for(Horse horse : horses) { System.out.println(horse.tracks()); // Print the track of each horse}for (Horse horse : horses) {
if (horse.getStrides() >= FINISH_LINE) {
System.out.println(horse + "won!"); // Every time a horse finishes, terminate all threads exec.shutdownNow();return; } } try { TimeUnit.MILLISECONDS.sleep(pause); Catch (InterruptedException e) {system.out.println (InterruptedException e) {system.out.println ("barrier-action sleep interrupted"); }}});for(int i = 0; i < nHorses; i++) { Horse horse = new Horse(barrier); horses.add(horse); exec.execute(horse); }} public static void main(String[] args) {int nHorses = 7; int pause = 200; new HorseRace(nHorses, pause); }}Copy the code
Let’s say the track is 75, and the horses take 0,1 or 2 steps at a time, and after each turn, they wait for each other. Once all the horses have cleared the fence, it will automatically be ready for the next round. Readers can run my program and display certain animation effects on the console.
In the example above, we provide a “fence action” to the CyclicBarrier, which is a Runnable that executes automatically when the count reaches zero, another difference between CyclicBarrier and CountDownLatch.
public CyclicBarrier(int parties, Runnable barrierAction)
Copy the code
CyclicBarrier also provides other useful methods, such as the getNumberWaiting method to get the number of threads blocked by a CyclicBarrier. The isBroken method is used to know if a blocking thread is interrupted. For example, the following code will return true after execution.