Two usages of CyclicBarrier [java multithreading]

CyclicBarrier

A synchronization helper class that allows a group of threads to wait on each other until some common barrier point is reached. CyclicBarrier is useful in programs involving a set of fixed-size threads that must wait for each other from time to time. Because the barrier can be reused after releasing the waiting thread, it is called a cyclic barrier. CyclicBarrier supports an optional Runnable command that runs only once at each barrier point after the last thread in a set of threads has arrived (but before all threads are released). This barrier operation is useful to update shared state before continuing with all participating threads.

   JDK1.8 official example

 

class Solver {
   final int N;
   final float[][] data;
   final CyclicBarrier barrier;

   class Worker implements Runnable {
     int myRow;
     Worker(int row) { myRow = row; }
     public void run() {
       while (!done()) {
         processRow(myRow);

         try {
           barrier.await();
         } catch (InterruptedException ex) {
           return;
         } catch (BrokenBarrierException ex) {
           return;
         }
       }
     }
   }

   public Solver(float[][] matrix) {
     data = matrix;
     N = matrix.length;
     Runnable barrierAction =
       new Runnable() { public void run() { mergeRows(...); }};
     barrier = new CyclicBarrier(N, barrierAction);

     List<Thread> threads = new ArrayList<Thread>(N);
     for (int i = 0; i < N; i++) {
       Thread thread = new Thread(new Worker(i));
       threads.add(thread);
       thread.start();
     }

     // wait until done
     for (Thread thread : threads)
       thread.join();
   }
 }

In this example, each worker thread processes one row of the matrix and will wait at the barrier until all rows have been processed. After all rows have been processed, the provided Runnable barrier operation is performed and the rows are merged. If the merger determines that a solution has been found, then done() will return true and all worker threads will terminate. If the barrier operation does not depend on the thread being suspended, any thread in the thread group can perform the operation when it is released. To facilitate this, each call to await() returns the index of the thread that can reach the barrier. You can then choose which thread should perform the barrier operation, for example: if (barrier.await() == 0) { // log the completion of this iteration } For failed synchronization attempts, CyclicBarrier uses an all-or-nothing All-or-none destruction mode: If a thread leaves a barrier point prematurely due to an interrupt, failure, or timeout, all other threads waiting at that barrier point will also pass a BrokenBarrierException (if they almost If interrupted at the same time, use InterruptedException) to leave in an abnormal way. Memory consistency effect: the operations before calling await() in the thread happen-before those are operations that are part of the barrier operation, which in turn happen-before followed by the operations corresponding to the successful return of await() from another thread .

For details, see: https://docs.oracle.com/javase/8/docs/api/

 

 

   Method 1: CyclicBarrier (int parties)

Creates a new CyclicBarrier that will start when a given number of participants (threads) are waiting, but it will not perform a predefined action when starting the barrier.

 

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;


public class CyclicBarrierTest {

    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
        CyclicBarrier barrier = new CyclicBarrier(2);
        Thread thread1 = new Thread(new XThread(barrier), "1号线程");
        Thread thread2 = new Thread(new XThread(barrier), "2号线程");
        thread1.start();
        thread2.start();
        System.out.println(Thread.currentThread().getName() + "执行");
    }
}

class XThread implements Runnable {
    private CyclicBarrier barrier;

    public XThread(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    public void run() {
        try {
            Thread.sleep(1000 * (new Random()).nextInt(5));
            System.out.println(Thread.currentThread().getName() + " 等待");
            barrier.await();
            System.out.println(Thread.currentThread().getName() + " 继续");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

   方式二:CyclicBarrier(int parties, Runnable barrierAction)

创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,并在启动 barrier 时执行给定的屏障操作,该操作由最后一个进入 barrier 的线程执行。

 

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;


public class CyclicBarrierDemo {
    public static void main(String[] args) throws InterruptedException, BrokenBarrierException {
        CyclicBarrier barrier = new CyclicBarrier(2, new Thread("barrierAction") {
            public void run() {
                System.out.println(Thread.currentThread().getName() + " 栅栏");

            }
        });
        Thread thread1 = new Thread(new SonThread(barrier), "1号线程");
        Thread thread2 = new Thread(new SonThread(barrier), "2号线程");
        thread1.start();
        thread2.start();
        System.out.println(Thread.currentThread().getName() + "执行");
    }
}

class SonThread implements Runnable {
    private CyclicBarrier barrier;

    public SonThread(CyclicBarrier barrier) {
        this.barrier = barrier;
    }

    public void run() {
        try {
            Thread.sleep(1000 * (new Random()).nextInt(5));
            System.out.println(Thread.currentThread().getName() + " 等待");
            barrier.await();
            System.out.println(Thread.currentThread().getName() + " 继续");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 

 


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326351507&siteId=291194637