朋友结婚,我来安排

一、缘由

朋友小月鸟要结婚了,因为疫情原因他想简单办,请几个朋友吃个饭,然后各回各家各找个媳妇儿(我没有),谁来安排这个流程呢?当然是我了,我还欠小月鸟一个月房租没给呢,帮他安排流程就当还债了吧。

二、流程

参与人数总数: 5人

参与人详情:小月月、小强、小明(我)、新人小月鸟、新人新娘。

流程:大家一起到了、大家一起吃饭、大家各自回家、两位新人过小日子。

不明白吗,那我画一个流程图给大家看看:

朋友结婚,我来安排_流程图

三、码农体质

身为互联网开发工作者的我,怎么可能这么简单一张流程图就结束呢?

上菜Phaser

package test;

import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

/**
 * @author 发现更多精彩  关注公众号:木子的昼夜编程
 * 一个生活在互联网底层,做着增删改查的码农,不谙世事的造作
 * @create 2021-08-21 17:06
 */

public class PhaserTest {
    public static void main(String[] args) {
        Phaser phaser = new MyPhaser();
        // 到5个人就进行下一个步骤
        phaser.bulkRegister(5);
        // 开始执行
        new Thread(new Person("小月月", phaser)).start();
        new Thread(new Person("小强", phaser)).start();
        new Thread(new Person("小明", phaser)).start();
        new Thread(new Person("新人小月鸟", phaser)).start();
        new Thread(new Person("新人新娘", phaser)).start();
    }
}

class MyPhaser extends Phaser {
    @Override
    protected boolean onAdvance(int phase, int registeredParties) {
        switch (phase) {
            case 0:
                System.out.println("大家都到了!");
                System.out.println();
                // 返回false 接着执行 返回true结束
                return false;
            case 1:
                System.out.println("大家一起吃饭!");
                System.out.println();
                // 返回false 接着执行 返回true结束
                return false;
            case 2:
                System.out.println("大家说拜拜!");
                System.out.println();
                // 返回false 接着执行 返回true结束
                return false;
            case 3:
                System.out.println("过小日子!");
                // 返回false 接着执行 返回true结束
                return true;
            default:
                return true;
        }
    }
}

class Person implements Runnable{
    public Person(){}
    public Person(String name, Phaser phaser) {
        this.name = name;
        this.phaser = phaser;
    }
    // 名称
    private String name;
    private Phaser phaser;


    @Override
    public void run() {
        // 到达
        arrived();
        // 准备吃饭
        eat();
        // 准备走了
        go();
        // 生活
        life();
    }

    public void arrived(){
        sleepRandom();
        System.out.println(name+"到了~");
        // 到达 类似于CyclicBarrier 的await()
        phaser.arriveAndAwaitAdvance();
    }
    public void eat(){
        sleepRandom();
        System.out.println(name+"准备吃饭~");
        phaser.arriveAndAwaitAdvance();
    }
    public void go(){
        sleepRandom();
        System.out.println(name+"准备走了~");
        if (name.contains("新人")) {
            phaser.arriveAndAwaitAdvance();
        } else {
            // 取消注册 phaser.bulkRegister(5); 本来是5个人 这里取消一次就少一个人
            //
            phaser.arriveAndDeregister();
        }
    }
    public void life(){
        sleepRandom();
        if (name.contains("新人")) {
            System.out.println(name+"过日子~");
            phaser.arriveAndAwaitAdvance();
        }
    }


    // 随机sleep几秒 来模拟人的不确定性
    public void sleepRandom(){
        try{
            TimeUnit.SECONDS.sleep((long) (Math.random()*10+1));
        } catch (Exception e) {
            System.out.println("异常了~~");
        }
    }
}

小提示:

sleepRandom: 随机停止1~10秒 模拟人的不确定性

bulkRegister:指定有多少个人到了就进行下个环节

arriveAndAwaitAdvance:到了并等待进行下个环节

arriveAndDeregister:到达并取消注册,也就是下个环节需要的总数减少了

onAdvance:

这个方法中的phase参数 表示当前到了第几个环节(从0开始)

这个方法的registeredParties参数表示这个环节有几个人需要参与

下边是某一次的输出结果:

朋友结婚,我来安排_ide_02

四、唠唠

学习Phaser的时候可以对比CyclicBarrier学习,都是指定人数到达某一个节点,然后才可以进行某一个环节

CyclicBarrier是可以循环使用,而Phaser是一次性的但是分多个阶段(类比为循环多次CyclicBarrier)

主要方法:

arriveAndAwaitAdvance(): 到达并前进  等大家都到了进行下一步
arriveAndDeregister(): 取消注册 离开队伍 以后你们怎么样不关我事
register(): 进入队伍  以后你们必须等我才能一起干事儿
bulkRegister(int parties):设置默认几个人参与  可以类比执行多次register
awaitAdvance(int phase):组团来的 一下子来好几个 可以类比执行
    了多次arriveAndAwaitAdvance
forceTermination: 强制结束 因为疫情不让超过4人吃饭 大家灰溜溜回家去吧
awaitAdvanceInterruptibly(int phase):这个很神奇 当前阶段如果等于phase那就等着人全到达了执行后续逻辑
    如果当前阶段不是phase或者被中断或者phaser已经结束 直接返回下个阶段的值或者是负数(如果结束)
awaitAdvanceInterruptibly(int phase,long timeout, TimeUnit unit) 带超时的 超过一定时间人数没凑齐那就返回
还有一些get方法 就是获取一些当前的阶段或者当前阶段到达人数或者应该到达人数等

对这个知识点,建议了解就可以,如果有时间先学习别的知识,时间实在充足的话可以看看他的一些源码and 其他知识点

我浏览了一下源码大概能看到用到了LockSupport等待和通过 compareAndSet线程安全的修改状态值

还有各种运算符**>>>** 、& 、三元运算符等

有事儿没事儿关注公众号:木子的昼夜编程