面试官: Phaser有了解过吗?说说看

简介: 面试官: Phaser有了解过吗?说说看

前言

目前正在出一个Java多线程专题长期系列教程,从入门到进阶含源码解读, 篇幅会较多, 喜欢的话,给个关注❤️ ~


Java提供了一些非常好用的并发工具类,不需要我们重复造轮子,本节我们讲解Phaser,一起来看下吧~


Phaser

Phaser又称“阶段器”,用来解决多线程分阶段任务的场景。它与CountDownLatch和CyclicBarrier类似,都是等待一组线程完成工作后再执行下一步。但CountDownLatch和CyclicBarrier中不能动态的配置parties,而Phaser可以动态注册,相对而言更加的灵活。


常用方法

  • int register() 动态添加一个parties
  • int bulkRegister(int parties) 动态添加多个parties
  • int getRegisteredParties() 获取当前的parties数
  • int arriveAndAwaitAdvance() 到达并等待其他线程到达
  • int arriveAndDeregister() 到达并注销该parties,这个方法不会使线程阻塞
  • int arrive() 到达,但不会使线程阻塞
  • int awaitAdvance(int phase) 等待前行,可阻塞也可不阻塞,判断条件为phase,如果相等则阻塞
  • int awaitAdvanceInterruptibly(int phase) 该方法与awaitAdvance类似,唯一不一样的就是它可以进行打断。
  • int awaitAdvanceInterruptibly(int phase, long timeout, TimeUnit unit) 同上
  • int getArrivedParties() 获取当前到达的parties数
  • int getUnarrivedParties() 获取当前未到达的parties数
  • int getPhase() 获取当前属于第几阶段,默认从0开始,最大为integer的最大值
  • boolean isTerminated() 判断当前phaser是否关闭
  • void forceTermination()  强制关闭当前phaser


示例

基本上把能用到的方法都给大家介绍了,下面我们通过一个例子实际体验一下:

public class PhaserTest {
    public static void main(String[] args) {
        Phaser phaser = new Phaser(10);
        for (int i=0; i<10; i++){
            new Thread(() -> {
                try {
                    long millis = System.currentTimeMillis();
                    System.out.println(millis + "--1-->当前处于"+phaser.getPhase()+"阶段");
                    Thread.sleep(1000);
                    // wait
                    phaser.arriveAndAwaitAdvance();
                    System.out.println(millis + "---2--->当前处于"+phaser.getPhase()+"阶段");
                    Thread.sleep(1000);
                    // wait
                    phaser.arriveAndAwaitAdvance();
                    System.out.println(millis + "---3--->当前处于"+phaser.getPhase()+"阶段");
                    Thread.sleep(1000);
                    // wait
                    phaser.arriveAndAwaitAdvance();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
        System.out.println("主线程");
    }
}
复制代码


实际输出:

1659925927951--1-->当前处于0阶段
主线程
1659925927951--1-->当前处于0阶段
1659925927951--1-->当前处于0阶段
1659925927950--1-->当前处于0阶段
1659925927951--1-->当前处于0阶段
1659925927951--1-->当前处于0阶段
1659925927951--1-->当前处于0阶段
1659925927951--1-->当前处于0阶段
1659925927950--1-->当前处于0阶段
1659925927951--1-->当前处于0阶段
1659925927951---2--->当前处于1阶段
1659925927950---2--->当前处于1阶段
1659925927951---2--->当前处于1阶段
1659925927950---2--->当前处于1阶段
1659925927951---2--->当前处于1阶段
1659925927951---2--->当前处于1阶段
1659925927951---2--->当前处于1阶段
1659925927951---2--->当前处于1阶段
1659925927951---2--->当前处于1阶段
1659925927951---2--->当前处于1阶段
1659925927951---3--->当前处于2阶段
1659925927951---3--->当前处于2阶段
1659925927950---3--->当前处于2阶段
1659925927951---3--->当前处于2阶段
1659925927950---3--->当前处于2阶段
1659925927951---3--->当前处于2阶段
1659925927951---3--->当前处于2阶段
1659925927951---3--->当前处于2阶段
1659925927951---3--->当前处于2阶段
1659925927951---3--->当前处于2阶段
复制代码

可以看出并不会造成主线程的阻塞,任务也是分阶段去完成的, 其它方法就不一一演示了,大家可以自行操作一下


结束语

本节主要讲解它的一个使用,有兴趣的同学可以看一下它的底层源码实现,相对于前两个要复杂一点,这里就不过多介绍。下一节,给大家讲下Fork/Join框架,关注我,不迷路 ~

相关文章
|
7月前
|
安全 Java 程序员
惊呆了!Java多线程里的“synchronized”竟然这么神奇!
【6月更文挑战第20天】Java的`synchronized`关键字是解决线程安全的关键,它确保同一时间只有一个线程访问同步代码。在案例中,`Counter`类的`increment`方法如果不加同步,可能会导致竞态条件。通过使用`synchronized`方法或语句块,可以防止这种情况,确保线程安全。虽然同步会带来性能影响,但它是构建并发应用的重要工具,平衡同步与性能是使用时需考虑的。了解并恰当使用`synchronized`,能有效应对多线程挑战。
23 1
|
8月前
|
Java
面试官:说一说CyclicBarrier的妙用!我:这个没用过...
【5月更文挑战第5天】面试官:说一说CyclicBarrier的妙用!我:这个没用过...
60 2
|
8月前
|
Java
面试官:实战中用过CountDownLatch吗?详细说一说,我:啊这...
【5月更文挑战第4天】面试官:实战中用过CountDownLatch吗?详细说一说,我:啊这...
56 1
|
设计模式 Java API
终于弄懂AQS了
大家好,我是三友~~ 相信大家对Java中的Lock锁应该不会陌生,比如ReentrantLock,锁主要是用来解决解决多线程运行访问共享资源时的线程安全问题。那你是不是很好奇,这些Lock锁api是如何实现的呢?本文就是来探讨一下这些Lock锁底层的AQS(AbstractQueuedSynchronizer)到底是如何实现的。

热门文章

最新文章