多线程之Phaser

简介

Phaser由java7中推出,是java7中新增的一个使用同步工具,在功能上面它与CyclicBarrier、CountDownLatch有些重叠,但是它提供了更加灵活、强大的用法。

CyclicBarrier,允许一组线程互相等待,直到到达某个公共屏障点。它提供的await()可以实现让所有参与者在临界点到来之前一直处于等待状态。

CountDownLatch,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。它提供了await()、countDown()两个方法来进行操作。

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


Phaser代替CountDownLatch

package com.example.demo.three.untils.phaser;

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

/**
 * @Author: CYM
 * @Description:
 * @Data: 2017/10/14 21:01
 */
public class PhaserTest1 {

    public static void main(String[] args) {
        final Phaser phaser = new Phaser(6);
        for (int i = 1; i <= 5; i++) {
            new Task(phaser).start();
        }
        phaser.arriveAndAwaitAdvance();

        System.out.println("===========");
    }

    static class Task extends Thread {
        private final Phaser phaser;

        Task(Phaser phaser) {
            this.phaser = phaser;

        }

        @Override
        public void run() {
            System.out.println("working: +" + Thread.currentThread().getName()+"--");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            phaser.arriveAndAwaitAdvance();
        }
    }
}

Phaser代替CyclicBarrier

package com.example.demo.three.untils.phaser;

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

/**
 * @Author: CYM
 * @Description:
 * @Data: 2017/10/14 21:01
 */
public class PhaserTest2 {

    /**
     * 所有线程执行完A,再执行B,所有线程执行完B后,再执行C.........
     * 类似 : CyclicBarrier
     * @param args
     */
    public static void main(String[] args) {
        final Phaser phaser = new Phaser(3);
        for (int i = 1; i <= 3; i++) {
            new Task(phaser).start();
        }

    }

    static class Task extends Thread {
        private final Phaser phaser;

        Task(Phaser phaser) {
            this.phaser = phaser;
        }

        @Override
        public void run() {
            try {
                System.out.println( Thread.currentThread().getName()+"-----A-----start");
                TimeUnit.SECONDS.sleep(2);
                System.out.println( Thread.currentThread().getName()+"-----A-----end");
                phaser.arriveAndAwaitAdvance();

                System.out.println( Thread.currentThread().getName()+"-----B-----start");
                TimeUnit.SECONDS.sleep(2);
                System.out.println( Thread.currentThread().getName()+"-----B-----end");
                phaser.arriveAndAwaitAdvance();

                System.out.println( Thread.currentThread().getName()+"-----C-----start");
                TimeUnit.SECONDS.sleep(2);
                System.out.println( Thread.currentThread().getName()+"-----C-----end");
                phaser.arriveAndAwaitAdvance();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Phaser一些方法

package com.example.demo.three.untils.phaser;

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

/**
 * @Author: CYM
 * @Description:
 * @Data: 2017/10/14 21:01
 */
public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) throws InterruptedException {
        final Phaser phaser = new Phaser(1);

        //getPhase()获取到达第几个屏障 Returns the current phase number.
        System.out.println("getPhase: " + phaser.getPhase()); //0
        phaser.arriveAndAwaitAdvance();
        System.out.println("getPhase: " + phaser.getPhase()); //1
        phaser.arriveAndAwaitAdvance();
        System.out.println("getPhase: " + phaser.getPhase()); //2

        /**-------------------------------------------------------------------------------------------------*/

        //getRegisteredParties获取注册partis的数量   Returns the number of parties registered at this phaser
        System.out.println("getRegisteredParties: " + phaser.getRegisteredParties());//1
        //register()动态添加一个partis
        phaser.register();
        System.out.println("getRegisteredParties: " + phaser.getRegisteredParties());//2
        //bulkRegister()批量增加partis
        phaser.bulkRegister(2);
        System.out.println("getRegisteredParties: " + phaser.getRegisteredParties());//4

        /**-------------------------------------------------------------------------------------------------*/
        final Phaser phaser3 = new Phaser(4);
        phaser3.arriveAndDeregister();//parties减少一个
        System.out.println("getRegisteredParties1: " + phaser3.getRegisteredParties());//3

        /**-------------------------------------------------------------------------------------------------*/

        final Phaser phaser2 = new Phaser(5);
        for (int i = 1; i <= 3; i++) {
            new Task(phaser2).start();
        }
        TimeUnit.SECONDS.sleep(2);
        //getArrivedParties()已被使用partis
        //getUnarrivedParties()未被使用partis
        System.out.println("getArrivedParties:" + phaser2.getArrivedParties());  //3
        System.out.println("getUnarrivedParties:" + phaser2.getUnarrivedParties());//2
    }

    static class Task extends Thread {
        private final Phaser phaser;
        Task(Phaser phaser) {
            this.phaser = phaser;
        }
        @Override
        public void run() {
            phaser.arriveAndAwaitAdvance();
        }
    }
}

onAdvance(int phase, int registeredParties)

package com.example.demo.three.untils.phaser;

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

/**
 * @Author: CYM
 * @Description:
 * @Data: 2017/10/14 21:01
 */
public class Test2 {

    /**
     * @param args
     */
    public static void main(String[] args) throws InterruptedException {

        final Phaser phaser4 = new Phaser(3){
            /**
             * @param phase  到达第几个屏障
             * @param registeredParties  注册Parties数量
             * @return  true 第一次phaser.arriveAndAwaitAdvance()后,调用此方法,之后Phaser呈无效/销毁状态
             *          false 多次调用phaser.arriveAndAwaitAdvance(),Phaser继续工作
             */
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                System.err.println("进入onAdvance:" + phase+registeredParties);
                return true;
            }
        };
        for (int i = 1; i <= 3; i++) {
            new Task(phaser4).start();
        }
    }

    static class Task extends Thread {
        private final Phaser phaser;
        Task(Phaser phaser) {
            this.phaser = phaser;
        }
        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName()+"---1---");
                TimeUnit.SECONDS.sleep(2);
                phaser.arriveAndAwaitAdvance();
                TimeUnit.SECONDS.sleep(2);
                System.out.println(Thread.currentThread().getName()+"===2===");

                System.out.println("是否销毁:" + phaser.isTerminated());

                if (Thread.currentThread().getName().equals("Thread-0")){
                    TimeUnit.SECONDS.sleep(10);
                }
                phaser.arriveAndAwaitAdvance();
                TimeUnit.SECONDS.sleep(1);
                System.out.println("*********");

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

        }
    }
}

arrive()

跟arriveAndAwaitAdvance()相比,不用等待。

public static void main(String[] args) throws InterruptedException {
        final Phaser phaser = new Phaser(2);
        new Thread(phaser::arrive).start(); //Arrives at this phaser,without waiting for others to arrive.
        System.out.println("*********");
        new Thread(phaser::arriveAndAwaitAdvance).start();
        System.out.println("*********");
    }

awaitAdvance(phase)

如果当前传入参数phase和getPhase()方法返回的值一样。则在屏障处等待,直到两者值不一样。不可被打中断。并不参与parties计数。

public class Test4 {

    /**
     * @param args
     */
    public static void main(String[] args) throws InterruptedException {
        final Phaser phaser = new Phaser(4);
        for (int i = 0; i <= 3; i++) {
            new Task(phaser).start();
        }
        final int phase = phaser.getPhase();
        /**awaitAdvance(phase):如果当前传入参数phase和getPhase()方法
         * 返回的值一样。则在屏障处等待,直到两者值不一样。不可被打中断
         *
         * 分析:传入参数phase=0,phaser.awaitAdvance(0)会一直等待,当第一次所有线程
         * 执行到phaser.arriveAndAwaitAdvance(),这时phaser.getPhase()为1,phaser.awaitAdvance(0)
         * 放行。
         *
         * 输出结果: *****1****1
                     *****1****1
                     *****1****1
                     *****1****1
                     *********0
                     *****2****2
                     *****2****2
                     *****2****2
                     *****2****2
         */
        phaser.awaitAdvance(phase);
        System.out.println("*********" + phase);

        /**----------------------------------------*/
        /**
         * awaitAdvance(int phase) 并不参与parties计数
         *
         * 结果:从输出结果可以看到:phaser1.getArrivedParties()为0
         */
        final Phaser phaser1 = new Phaser(4);
        new Thread(()->phaser1.awaitAdvance(0)).start();
        TimeUnit.SECONDS.sleep(20);
        System.err.println(phaser1.getArrivedParties());

    }

    static class Task extends Thread {
        private final Phaser phaser;

        Task(Phaser phaser) {
            this.phaser = phaser;
        }

        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(1);
                phaser.arriveAndAwaitAdvance();
                System.out.println("*****1****"+phaser.getPhase());

                TimeUnit.SECONDS.sleep(1);
                phaser.arriveAndAwaitAdvance();
                System.out.println("*****2****"+phaser.getPhase());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

awaitAdvanceInterruptibly(int phase)可被中断.
awaitAdvanceInterruptibly(int phase,long timeout, TimeUnit unit) 最多等待指定时间,可中断.


forceTermination()

 public static void main(String[] args) throws InterruptedException {
        final Phaser phaser = new Phaser(3);
        new Thread(phaser::arriveAndAwaitAdvance).start();

        TimeUnit.SECONDS.sleep(3);
        System.out.println(phaser.isTerminated());
        phaser.forceTermination();
        System.out.println(phaser.isTerminated());

    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值