线程同步工具类[2]

Phaser

适用于分阶段的线程同步. 可以在构造时设置一个初始的参与的线程个数, 也可以后边通过方法注册与注销. 所以它的生命周期内参与的线程数是可以变化的. 当其中参与的线程到达某个phase的确认点之后, 可以选择等待,或直接继续, 或者不参与到下一个phase.
Phaser内部维护phase的数值, 记录当前那些phase到达的数量, 但是不会维护参与者的信息. 这里有个很重要的概念是: Phase 并不管有多少线程, 它只管每个阶段达到方法被调用的次数, 只要被调用的次数足够, 它就到下一阶段, 典型的是Phaser的注册数有N个, 但是这N全是一个线程在调用arrive() 方法. 当然如果是要求多个同步, 一般是多个线程调用arriveAndAwaitAdvance(). 这个phase 数值从0 开始, 当要求的参与者都到达之后加一.

public int arrive() 方法不会等待其他参与者, 当此线程下次调用相关的arrive*()方法的时候, 有可能还是当前phase, 是当前phase的到达者加一. 如
public static void main(String[] args) {
Phaser p = new Phaser(3);

    System.out.println(p.arrive());
    System.out.println(p.arrive());
    System.out.println(p.arrive());
    
    System.out.println(p.arrive());
    System.out.println(p.arrive());
    System.out.println(p.arrive());
    p.forceTermination();
}

public int arriveAndAwaitAdvance() 方法等同于awaitAdvance(arrive()), 和 CyclicBarrier的await() 方法类似.

不等待: arrive();
不等待并且使参与者减少一个: arriveAndDeregister()
等待这一个phase结束并且使参与者减少一个: awaitAdvance(arriveAndDeregister())

public int awaitAdvance(int phase) 这个方法很容易让人迷糊, 以为它会一直等待第N phase, 其实不然, 只要是当前phase 和N 不相等, 就立马返回. 所以, 如果你想真正的等待第N phase, 那么你可能需要这么做:
while (p.getPhase() < N) {
p.awaitAdvance(p.getPhase()); // 前提是你N之前都没注册
}
//此处已到N或者N+

protected boolean onAdvance(int phase, int registeredParties) 方法是在所有参与者到达后, 下一phase 开始之前执行的, 类似CyclicBarrier 的Action Command. 这个方法可以用来override 去替换一些特定的Action. 如果返回值是true, 则本phase 是最后一个阶段.
如果Phaser 已经终止, 则后面的await都会立马返回.

Exchanger

在一个同步点, 2个线程彼此通过Exchanger交换数据.

标签: none

添加新评论