CyclicBarrier2种用法【java多线程】

CyclicBarrier

一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该 barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。 CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作 很有用。

   JDK1.8官方示例

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();
   }
 }

在这个例子中,每个 worker 线程处理矩阵的一行,在处理完所有的行之前,该线程将一直在屏障处等待。处理完所有的行之后,将执行所提供的 Runnable 屏障操作,并合并这些行。如果合并者确定已经找到了一个解决方案,那么 done() 将返回 true,所有的 worker 线程都将终止。 如果屏障操作在执行时不依赖于正挂起的线程,则线程组中的任何线程在获得释放时都能执行该操作。为方便此操作,每次调用 await() 都将返回能到达屏障处的线程的索引。然后,您可以选择哪个线程应该执行屏障操作,例如: if (barrier.await() == 0) { // log the completion of this iteration } 对于失败的同步尝试,CyclicBarrier 使用了一种要么全部要么全不 (all-or-none) 的破坏模式:如果因为中断、失败或者超时等原因,导致线程过早地离开了屏障点,那么在该屏障点等待的其他所有线程也将通过 BrokenBarrierException(如果它们几乎同时被中断,则用 InterruptedException)以反常的方式离开。 内存一致性效果:线程中调用 await() 之前的操作 happen-before 那些是屏障操作的一部份的操作,后者依次 happen-before 紧跟在从另一个线程中对应 await() 成功返回的操作。

详情请见:https://docs.oracle.com/javase/8/docs/api/

   方式一:CyclicBarrier(int parties)

创建一个新的 CyclicBarrier,它将在给定数量的参与者(线程)处于等待状态时启动,但它不会在启动 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();
        }
    }
}

 


猜你喜欢

转载自xuhuanblog.iteye.com/blog/2408917