java - Phaser - 如何将其用作 CountDownLatch(1)?

标签 java multithreading concurrency java.util.concurrent phaser

我知道我可以直接使用 CountDownLatch,但是,作为练习并为了更好地理解 Phaser,我想使用它而不是 COuntDownLatch

因此,我将创建 N 个等待者,以及一个需要翻转锁存器的线程。所有等待者,如果在翻转之前到达,都会阻塞,但是在闩锁倒计时之后,所有后续的 await() 立即返回。

WIth Phaser 我不知道如何实现这一点...障碍很容易,因为我们有 N + 1 个线程,每个线程都到达并等待。然而,为了确保没有线程在第一阶段之后等待,不知何故,我感到困惑。

我能想到的唯一方法如下:

Phaser p = new Phaser(1);
int phase = p.getPhase();
....
// thread that awaits()
new Thread(new Runnable() {
    ....
    p.awaitAdvance(phase)
}

另一个线程只是将移相器推进到下一阶段。这并不理想,因此我们将不胜感激。

最佳答案

我不同意@tiago-cogumbreiro 的回答。事实上,Phaser可以用来模拟CountDownLatch的行为。

您可以使用 Phaser 的 arrive() 方法来实现它。它不会等待其他线程到达。因此,可以实现 CountDownLatch 行为。

Phaser 的 arriveAndAwaitAdvance() 使调用它的线程等待,直到其他线程/方到达。因此,该方法可用于模拟 CyclicBarrier 的行为。

下面是使用 Phaser 模拟 CountDownLatch(3) 行为的源代码。如果只使用一个WorkerThread,可以模拟CountDownLatch(1)

如果将 arrive() 方法替换为 arriveAndAwaitAdvance() 方法,下面的代码将模拟 CyclicBarrier

public class PhaserAsCountDownLatch {

    static Phaser phaser = new Phaser(3);

    public static void main(String[] args) {
     
        new WorkerThread2().start();
        new WorkerThread3().start();
        new WorkerThread().start();
        
        //waits till phase 0 is completed and phase is advanced to next.
        phaser.awaitAdvance(0); 
        
        System.out.println("\nFROM MAIN THREAD: PHASE 0 COMPLETED");
        System.out.println("FROM MAIN THREAD: PHASE ADVANCED TO 1");
        System.out.println("MAIN THREAD ENDS HERE\n");
    }

    static class WorkerThread extends Thread{
        @Override
        public void run() {
            for (int i = 1; i < 5; i++) {
                System.out.println("tid: " + Thread.currentThread().getId() +  ", BEFORE ARRIVING val is: " + i);
            }
        
            phaser.arrive();
        
            System.out.println("ARRIVED tid: " + Thread.currentThread().getId());
        }
    }

    static class WorkerThread2 extends Thread{
        @Override
        public void run() {
        
            //won't wait for other threads to arrive. Hence, CountDownLatch behaviour can be achieved
            phaser.arrive();
        
            System.out.println("ARRIVED tid: " + Thread.currentThread().getId());
            for (int i = 200; i < 231; i++) {
                System.out.println("tid: " + Thread.currentThread().getId() +  " AFTER ARRIVING. val is: " + i);
            }
        }
    }

    static class WorkerThread3 extends Thread{
        @Override
        public void run() {
        
            //won't wait for other threads to arrive. Hence, CountDownLatch behaviour can be achieved
            phaser.arrive();
        
            System.out.println("ARRIVED tid: " + Thread.currentThread().getId());
            for (int i = 300; i < 331; i++) {
                System.out.println("tid: " + Thread.currentThread().getId() +  " AFTER ARRIVING. val is: " + i);
            }
        }
    }
}

关于java - Phaser - 如何将其用作 CountDownLatch(1)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45600243/

相关文章:

c# - 遇到锁时如何停止线程?

c++ - tbb::concurrent_unordered_map::unsafe_erase 是否会使任何现有的迭代器失效?

java - EJB Singleton - Lock READ 方法调用同一实例的 Lock WRITE 方法

java - 如何在 (mm :ss) format using editText?

java - 并行运行 100 个线程,如果之前的一些线程已完成,则运行缺失的线程

java - 如何解决java中堆栈内存溢出错误

java - 如何杀死队列中等待执行Java方法的线程

java - 有没有办法从 URL 字节流的特定位置开始读取?

java - 在java中执行依赖任务

java - 从数据库中获取特定列的最新行