【十四】Java多线程J.U.C之 Phaser

版权声明:转载注明出处 https://blog.csdn.net/jy02268879/article/details/86014531

概述

Phaser把多个线程协作执行的任务划分为多个阶段,编程时需要明确各个阶段的任务,每个阶段都可以有任意个参与者,线程都可以随时注册并参与到某个阶段

Phaser比较适合这样一种场景,一种任务可以分为多个阶段,
现希望多个线程去处理该批任务,对于每个阶段,多个线程可以并发进行,
但是希望保证只有前面一个阶段的任务完成之后才能开始后面的任务。

方法简介

arriveAndAwaitAdvance() 当前线程当前阶段执行完毕,等待其它线程完成当前阶段,进入阻塞,直到Phaser成功进入下个阶段。
      如果当前线程是该阶段最后一个未到达的,则该方法直接返回下一个阶段的序号(阶段序号从0开始),同时其它线程的该方法也返回下一个阶段的序号。

arriveAndDeregister() 该方法立即返回下一阶段的序号,并且其它线程需要等待的个数减一,
      取消自己的注册、把当前线程从之后需要等待的成员中移除。
      如果该Phaser是另外一个Phaser的子Phaser(层次化Phaser),
      并且该操作导致当前Phaser的成员数为0,则该操作也会将当前Phaser从其父Phaser中移除。

arrive() 某个参与者完成任务后调用,该方法不作任何等待,直接返回下一阶段的序号。

awaitAdvance(int phase) 该方法等待某一阶段执行完毕。
      如果当前阶段不等于指定的阶段或者该Phaser已经被终止,则立即返回。
      该阶段数一般由arrive()方法或者arriveAndDeregister()方法返回。
      返回下一阶段的序号,或者返回参数指定的值(如果该参数为负数),或者直接返回当前阶段序号(如果当前Phaser已经被终止)。

awaitAdvanceInterruptibly(int phase) 效果与awaitAdvance(int phase)相当,
      唯一的不同在于若该线程在该方法等待时被中断,则该方法抛出InterruptedException。

 awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit)
      效果与awaitAdvanceInterruptibly(int phase)相当,
      区别在于如果超时则抛出TimeoutException。

bulkRegister(int parties) 动态调整注册任务parties的数量。如果当前phaser已经被终止,则该方法无效,并返回负数。
      如果调用该方法时,onAdvance方法正在执行,则该方法等待其执行完毕。
      如果该Phaser有父Phaser则指定的party数大于0,且之前该Phaser的party数为0,那么该Phaser会被注册到其父Phaser中。

forceTermination() 强制让该Phaser进入终止状态。
      已经注册的party数不受影响。如果该Phaser有子Phaser,则其所有的子Phaser均进入终止状态。
      如果该Phaser已经处于终止状态,该方法调用不造成任何影响。

 代码示例

示例 3个线程,4个阶段,每个阶段都并发处理

package com.sid.thread.PhaserTest;

import java.util.concurrent.Phaser;

/**
 * @program: thread-test
 *
 *      示例 3个线程,4个阶段,每个阶段都并发处理
 *
 * @author: Sid
 * @date: 2018-11-27 14:43
 * @since: 1.0
 **/
public class PhaserDemo {
    public static void main(String[] args) {
        int parties = 3;
        int phases = 4;
        final Phaser phaser = new Phaser(parties) {
            @Override
            //每个阶段结束时
            protected boolean onAdvance(int phase, int registeredParties) {
                System.out.println("====== Phase : " + phase + "  end ======");
                return registeredParties == 0;
            }
        };

        for(int i = 0; i < parties; i++) {
            int threadId = i;
            Thread thread = new Thread(() -> {
                for(int phase = 0; phase < phases; phase++) {
                    if(phase==0) {
                        System.out.println(String.format("第一阶段的逻辑操作  Thread %s, phase %s", threadId, phase));
                    }
                    if(phase==1) {
                        System.out.println(String.format("第二阶段的逻辑操作  Thread %s, phase %s", threadId, phase));
                    }
                    if(phase==2) {
                        System.out.println(String.format("第三阶段的逻辑操作  Thread %s, phase %s", threadId, phase));
                    }
                    if(phase==3) {
                        System.out.println(String.format("第四阶段的逻辑操作  Thread %s, phase %s", threadId, phase));
                    }
                    /**
                     * arriveAndAwaitAdvance() 当前线程当前阶段执行完毕,等待其它线程完成当前阶段。
                     * 如果当前线程是该阶段最后一个未到达的,则该方法直接返回下一个阶段的序号(阶段序号从0开始),
                     * 同时其它线程的该方法也返回下一个阶段的序号。
                     * */
                    int nextPhaser = phaser.arriveAndAwaitAdvance();

                }
            });
            thread.start();
        }
    }
}

运行结果

第一阶段的逻辑操作  Thread 1, phase 0
第一阶段的逻辑操作  Thread 2, phase 0
第一阶段的逻辑操作  Thread 0, phase 0
====== Phase : 0  end ======
第二阶段的逻辑操作  Thread 2, phase 1
第二阶段的逻辑操作  Thread 0, phase 1
第二阶段的逻辑操作  Thread 1, phase 1
====== Phase : 1  end ======
第三阶段的逻辑操作  Thread 1, phase 2
第三阶段的逻辑操作  Thread 2, phase 2
第三阶段的逻辑操作  Thread 0, phase 2
====== Phase : 2  end ======
第四阶段的逻辑操作  Thread 0, phase 3
第四阶段的逻辑操作  Thread 2, phase 3
第四阶段的逻辑操作  Thread 1, phase 3
====== Phase : 3  end ======

Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/jy02268879/article/details/86014531