阶段终止后的 java.util.concurrent.Phaser 回调

标签 java concurrency synchronization phaser

我调查了 java.util.concurrent 包中的 Phaser 并编写了代码示例:

public class ThreadsApp {

    public static void main(String[] args) {

        Phaser phaser = new Phaser(1);
        new Thread(new PhaseThread(phaser, "PhaseThread 1")).start();
        new Thread(new PhaseThread(phaser, "PhaseThread 2")).start();

        // ждем завершения фазы 0
        int phase = phaser.getPhase();
        phaser.arriveAndAwaitAdvance();
        System.out.println("phase " + phase + " finished");
        // ждем завершения фазы 1
        phase = phaser.getPhase();
        phaser.arriveAndAwaitAdvance();
        System.out.println("phase " + phase + " finished");

        // ждем завершения фазы 2
        phase = phaser.getPhase();
        phaser.arriveAndAwaitAdvance();
        System.out.println("phase " + phase + " finished");

        phaser.arriveAndDeregister();
    }
}

class PhaseThread implements Runnable {

    Phaser phaser;
    String name;

    PhaseThread(Phaser p, String n) {

        this.phaser = p;
        this.name = n;
        phaser.register();
    }

    public void run() {
        try {
            System.out.println(name + " start execute phase " + phaser.getPhase());
            Thread.sleep(1000);
            phaser.arriveAndAwaitAdvance(); // сообщаем, что первая фаза достигнута

            System.out.println(name + " start execute phase " + phaser.getPhase());
            Thread.sleep(2000);
            phaser.arriveAndAwaitAdvance(); // сообщаем, что вторая фаза достигнута

            System.out.println(name + " start execute phase " + phaser.getPhase());
            Thread.sleep(3000);
            phaser.arriveAndDeregister(); // сообщаем о завершении фаз и удаляем с регистрации объекты

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出:

PhaseThread 2 start execute phase 0
PhaseThread 1 start execute phase 0
PhaseThread 2 start execute phase 1
phase 0 finished
PhaseThread 1 start execute phase 1
phase 1 finished
PhaseThread 1 start execute phase 2
PhaseThread 2 start execute phase 2
phase 2 finished

输出与我想要的有点不同:

我想要:

PhaseThread 2 start execute phase 0
PhaseThread 1 start execute phase 0
phase 0 finished
PhaseThread 2 start execute phase 1
PhaseThread 1 start execute phase 1
phase 1 finished
PhaseThread 1 start execute phase 2
PhaseThread 2 start execute phase 2
phase 2 finished

因此,我希望 phase X finish 将在 PhaseThread # startexecute stage X 和 strict before PhaseThread strict after 之间打印# 开始执行阶段X+1

我明白为什么我的代码工作不正常,但我不知道如何实现所需的行为。我认为这是可能的,因为到处都写有 Phaser 涵盖 CyclicBarrier 功能。

最佳答案

阅读 Phaser 的 Java 文档显示了一个名为 onAdvance 的重写方法,该方法可用于在阶段实际完成时打印 X 阶段完成。只需修改如下代码即可。

public class ThreadsApp {

    public static void main(String[] args) {

        Phaser phaser = new Phaser(1) {
            protected boolean onAdvance(int phase, int parties) { 
                System.out.println("phase " + phase + " finished");
                return false; 
            }
        };
        new Thread(new PhaseThread(phaser, "PhaseThread 1")).start();
        new Thread(new PhaseThread(phaser, "PhaseThread 2")).start();

        // ждем завершения фазы 0
        int phase = phaser.getPhase();
        phaser.arriveAndAwaitAdvance();

        // ждем завершения фазы 1
        phase = phaser.getPhase();
        phaser.arriveAndAwaitAdvance();


        // ждем завершения фазы 2
        phase = phaser.getPhase();
        phaser.arriveAndDeregister();
    }
}

class PhaseThread implements Runnable {

    Phaser phaser;
    String name;

    PhaseThread(Phaser p, String n) {

        this.phaser = p;
        this.name = n;
        phaser.register();
    }

    public void run() {
        try {
            System.out.println(name + " start execute phase " + phaser.getPhase());
            Thread.sleep(1000);
            phaser.arriveAndAwaitAdvance(); // сообщаем, что первая фаза достигнута

            System.out.println(name + " start execute phase " + phaser.getPhase());
            Thread.sleep(2000);
            phaser.arriveAndAwaitAdvance(); // сообщаем, что вторая фаза достигнута

            System.out.println(name + " start execute phase " + phaser.getPhase());
            Thread.sleep(3000);
            phaser.arriveAndDeregister(); // сообщаем о завершении фаз и удаляем с регистрации объекты

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

关于阶段终止后的 java.util.concurrent.Phaser 回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41894225/

相关文章:

java - Android 日历设置上午或下午时间不是 24 小时

java - JPA 中的验证模式

java - 仅使用 JDK (6) 提供的类来改进该代码的方法? (并发、线程安全)

c# - ConcurrentDictionary + Lazy——实例化只会发生一次吗?

wcf - 在 WCF 服务中调用 STA Visual Basic 6.0 COM 对象的最佳实践 : Concurrent access

synchronization - Java synchronized() block 的 golang 等价物是什么?

java - 同步列表时的操作顺序

java - Hibernate:保存一侧具有唯一约束的链接表

java - 为什么我们使用 system.out.flush()?

operating-system - 预防死锁 :Mutual Exclusion