美文网首页
java.util.concurrent 闭锁 CountDow

java.util.concurrent 闭锁 CountDow

作者: dinel | 来源:发表于2020-04-28 22:24 被阅读0次

    闭锁 CountDownLatch

    java.util.concurrent.CountDownLatch 是一个并发构造,它允许一个或多个线程等待一系列指定操作的完成。
    CountDownLatch 以一个给定的数量初始化。countDown() 每被调用一次,这一数量就减一。
    通过调用 await() 方法之一,线程可以阻塞等待这一数量到达零。
    以下是一个简单示例。Decrementer 三次调用 countDown() 之后,等待中的 Waiter 才会从await() 调用中释放出来。

    CountDownLatch latch = new CountDownLatch(3);
    Waiter waiter = new Waiter(latch);
    Decrementer decrementer = new Decrementer(latch);
    new Thread(waiter) .start();
    new Thread(decrementer).start();
    Thread.sleep(4000);
    
    
    
    public class Waiter implements Runnable {
        CountDownLatch latch = null;
    
        public Waiter(CountDownLatch latch) {
            this.latch = latch;
        }
    
        public void run() {
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            System.out.println("Waiter Released");
        }
    }
    
    
    public class Decrementer implements Runnable {
        CountDownLatch latch = null;
    
        public Decrementer(CountDownLatch latch) {
            this.latch = latch;
        }
    
        public void run() {
            try {
                Thread.sleep(1000);
                this.latch.countDown();
                Thread.sleep(1000);
                this.latch.countDown();
                Thread.sleep(1000);
                this.latch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    

    栅栏 CyclicBarrier

    java.util.concurrent.CyclicBarrier 类是一种同步机制,它能够对处理一些算法的线程实现同步。换句话讲,它就是一个所有线程必须等待的一个栅栏,直到所有线程都到达这里,然后所有线程才可以继续做其他事情。图示如下:


    图片.png

    通过调用 CyclicBarrier 对象的 await() 方法,两个线程可以实现互相等待。一旦 N 个线程在等待 CyclicBarrier 达成,所有线程将被释放掉去继续运行。

    创建一个 CyclicBarrier

    在创建一个 CyclicBarrier 的时候你需要定义有多少线程在被释放之前等待栅栏。创建
    CyclicBarrier 示例:
    CyclicBarrier barrier = new CyclicBarrier(2);

    等待一个 CyclicBarrier

    以下演示了如何让一个线程等待一个 CyclicBarrier:
    barrier.await();
    当然,你也可以为等待线程设定一个超时时间。等待超过了超时时间之后,即便还没有达成
    N 个线程等待 CyclicBarrier 的条件,该线程也会被释放出来。以下是定义超时时间示例:
    barrier.await(10, TimeUnit.SECONDS);
    满足以下任何条件都可以让等待 CyclicBarrier 的线程释放:

    1. 最后一个线程也到达 CyclicBarrier(调用 await())
    2. 当前线程被其他线程打断(其他线程调用了这个线程的 interrupt() 方法) 其他等待栅栏的线程被打断
    3. 其他等待栅栏的线程因超时而被释放
    4. 外部线程调用了栅栏的 CyclicBarrier.reset() 方法

    CyclicBarrier 行动

    CyclicBarrier 支持一个栅栏行动,栅栏行动是一个 Runnable 实例,一旦最后等待栅栏的线程抵达,该实例将被执行。你可以在 CyclicBarrier 的构造方法中将 Runnable 栅栏行动传给它:
    Runnable barrierAction = ... ;
    CyclicBarrier barrier = new CyclicBarrier(2, barrierAction);

    CyclicBarrier 示例

    以下代码演示了如何使用 CyclicBarrier:

    Runnable barrier1Action = new Runnable() {
         public void run() {
             System.out.println("BarrierAction 1 executed ");
         }
    };
    Runnable barrier2Action = new Runnable() {
         public void run() {
           System.out.println("BarrierAction 2 executed ");
         }
    };
    CyclicBarrier barrier1 = new CyclicBarrier(2, barrier1Action);
    CyclicBarrier barrier2 = new CyclicBarrier(2, barrier2Action);
    CyclicBarrierRunnable barrierRunnable1 =
    new CyclicBarrierRunnable(barrier1, barrier2);
    CyclicBarrierRunnable barrierRunnable2 =
    new CyclicBarrierRunnable(barrier1, barrier2);
    new Thread(barrierRunnable1).start();
    new Thread(barrierRunnable2).start();
    
    

    CyclicBarrierRunnable 类:

    public class CyclicBarrierRunnable implements Runnable {
        CyclicBarrier barrier1 = null;
        CyclicBarrier barrier2 = null;
    
        public CyclicBarrierRunnable(CyclicBarrier barrier1, CyclicBarrier barrier2) {
            this.barrier1 = barrier1;
            this.barrier2 = barrier2;
        }
    
        public void run() {
            try {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() +
                    " waiting at barrier 1");
                this.barrier1.await();
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() +
                    " waiting at barrier 2");
                this.barrier2.await();
                System.out.println(Thread.currentThread().getName() + " done!");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    

    以上代码控制台输出如下。注意每个线程写入控制台的时序可能会跟你实际执行不一样。比
    如有时 Thread-0 先打印,有时 Thread-1 先打印。
    Thread-0 waiting at barrier 1
    Thread-1 waiting at barrier 1
    BarrierAction 1 executed
    Thread-1 waiting at barrier 2
    Thread-0 waiting at barrier 2
    BarrierAction 2 executed
    Thread-0 done!
    Thread-1 done!

    相关文章

      网友评论

          本文标题:java.util.concurrent 闭锁 CountDow

          本文链接:https://www.haomeiwen.com/subject/ynuiwhtx.html