【问题标题】:java.util.concurrent.Phaser callback after phase termination阶段终止后的 java.util.concurrent.Phaser 回调
【发布时间】:2017-06-13 03:35:55
【问题描述】:

我从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 finished 将在PhaseThread # start execute phase XPhaseThread # start execute phase X+1 之前strict after 打印出来

我了解我的代码为何无法正常运行,但我不知道如何实现所需的行为。我认为这是可能的,因为到处都写着 Phaser 覆盖 CyclicBarrier 功能。

【问题讨论】:

    标签: java concurrency synchronization phaser


    【解决方案1】:

    阅读Phaser 的Java Doc 显示了一个名为onAdvance 的覆盖方法,该方法可用于在阶段实际完成时打印phase X finished。修改如下代码即可。

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

    【讨论】:

    • 我不知道onAdvance不错,.线程打印start execute phase 的顺序当然不是100% 保证的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-05
    • 2012-11-12
    • 2017-07-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多