This is the 18th day of my participation in the August Genwen Challenge.More challenges in August
CyclicBarrier
CyclicBarrier literally means CyclicBarrier. What it does is allow a group of threads to block when they reach a barrier (also known as a synchronization point), and the barrier will not open until the last thread reaches the barrier, and all threads blocked by the barrier will continue to run.
The CyclicBarrier’s default constructor is CyclicBarrier (int parties), whose argument is the number of threads that the barrier intercepts, and each thread calls the await method to tell the CyclicBarrier that I have reached the barrier and the current thread is blocked.
public class CyclicBarrierTest {
static CyclicBarrier c = new CyclicBarrier(2);
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run(a) {
try {
c.await();
} catch (Exception e) {
}
System.out.println(1);
}
}).start();
try {
c.await();
} catch (Exception e) {
}
System.out.println(2); }}Copy the code
Since the scheduling of the primary and child threads is determined by the CPU, both threads may execute first, resulting in two outputs, 12 and 21
If you change new CyclicBarrier(2) to new CyclicBarrier(3), the main thread and child threads will wait forever because there is no third thread to execute the await method, that is, no third thread has reached the barrier, so neither of the two threads that reached the barrier before will continue to execute.
CyclicBarrier also provides a more advanced constructor CyclicBarrier (int parties, Runnable barrierAction) that takes precedence over barrierAction when a thread reaches a barrier, facilitating more complex business scenarios
public class CyclicBarrierTest2 {
static CyclicBarrier c = new CyclicBarrier(2.new A());
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run(a) {
try {
c.await();
} catch (Exception e) {
}
System.out.println(1);
}
}).start();
try {
c.await();
} catch (Exception e) {
}
System.out.println(2);
}
static class A implements Runnable {
@Override
public void run(a) {
System.out.println(3); }}}Copy the code
Because CyclicBarrier sets the number of intercepting threads to 2, the main thread must wait until the first thread in the code and thread A have finished executing, and then 312 is printed
public class BankWaterService implements Runnable {
/** * Create four barriers and execute the run method of the current class */ after processing
private CyclicBarrier c = new CyclicBarrier(4.this);
/** * assume only four sheets, so only four threads are started */
private Executor executor = Executors.newFixedThreadPool(4);
/** * Saves the silver flow results calculated by each sheet */
private ConcurrentHashMap<String, Integer> sheetBankWaterCount = new
ConcurrentHashMap<String, Integer>();
private void count(a) {
for (int i = 0; i < 4; i++) {
executor.execute(new Runnable() {
@Override
public void run(a) {
// Calculate the current sheet silver flow data, calculation code omitted
sheetBankWaterCount
.put(Thread.currentThread().getName(), 1);
// The silver flow is calculated and a barrier is inserted
try {
c.await();
} catch(Exception e) { e.printStackTrace(); }}}); }}@Override
public void run(a) {
int result = 0;
// Summarize the results calculated by each sheet
for (Map.Entry<String, Integer> sheet : sheetBankWaterCount.entrySet()) {
result += sheet.getValue();
}
// Print the result
sheetBankWaterCount.put("result", result);
System.out.println(result);
}
public static void main(String[] args) {
BankWaterService bankWaterCount = newBankWaterService(); bankWaterCount.count(); }}Copy the code
Create 4 threads using the thread pool, calculate the data in each sheet, calculate the result of each sheet 1, then the BankWaterService thread summarize the result of 4 sheets, output the result of 4
CountDownLatch’s counter can only be used once, while CyclicBarrier’s counter can be reset using the reset() method. So CyclicBarrier can handle more complex business scenarios. For example, if a calculation error occurs, you can reset the counter and have the thread execute again.
CyclicBarrier also provides other useful methods, such as the getNumberWaiting method that gets the number of threads blocked by CyclicBarrier. The isBroken() method is used to know if a blocking thread is interrupted
public class CyclicBarrierTest3 {
static CyclicBarrier c = new CyclicBarrier(2);
public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
Thread thread = new Thread(new Runnable() {
@Override
public void run(a) {
try {
c.await();
} catch (Exception e) {
}
}
});
thread.start();
thread.interrupt();
try {
c.await();
} catch(Exception e) { System.out.println(c.isBroken()); }}}Copy the code