java多线程之Phaser的使用详解

 更新时间:2020年03月31日 09:22:40   作者:flydean  
这篇文章主要介绍了java多线程之Phaser的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前面的文章中我们讲到了CyclicBarrier、CountDownLatch的使用,这里再回顾一下CountDownLatch主要用在一个线程等待多个线程执行完毕的情况,而CyclicBarrier用在多个线程互相等待执行完毕的情况。

Phaser是java 7 引入的新的并发API。他引入了新的Phaser的概念,我们可以将其看成一个一个的阶段,每个阶段都有需要执行的线程任务,任务执行完毕就进入下一个阶段。所以Phaser特别适合使用在重复执行或者重用的情况。

基本使用

在CyclicBarrier、CountDownLatch中,我们使用计数器来控制程序的顺序执行,同样的在Phaser中也是通过计数器来控制。在Phaser中计数器叫做parties, 我们可以通过Phaser的构造函数或者register()方法来注册。

通过调用register()方法,我们可以动态的控制phaser的个数。如果我们需要取消注册,则可以调用arriveAndDeregister()方法。

我们看下arrive:

 public int arrive() {
  return doArrive(ONE_ARRIVAL);
 }

Phaser中arrive实际上调用了doArrive方法,doArrive接收一个adjust参数,ONE_ARRIVAL表示arrive,ONE_DEREGISTER表示arriveAndDeregister。

Phaser中的arrive()、arriveAndDeregister()方法,这两个方法不会阻塞,但是会返回相应的phase数字,当此phase中最后一个party也arrive以后,phase数字将会增加,即phase进入下一个周期,同时触发(onAdvance)那些阻塞在上一phase的线程。这一点类似于CyclicBarrier的barrier到达机制;更灵活的是,我们可以通过重写onAdvance方法来实现更多的触发行为。

下面看一个基本的使用:

 void runTasks(List<Runnable> tasks) {
  final Phaser phaser = new Phaser(1); // "1" to register self
  // create and start threads
  for (final Runnable task : tasks) {
   phaser.register();
   new Thread() {
    public void run() {
     phaser.arriveAndAwaitAdvance(); // await all creation
     task.run();
    }
   }.start();
  }

  // allow threads to start and deregister self
  phaser.arriveAndDeregister();
 }

上面的例子中,我们在执行每个Runnable之前调用register()来注册, 然后调用arriveAndAwaitAdvance()来等待这一个Phaser周期结束。最后我们调用 phaser.arriveAndDeregister();来取消注册主线程。

多个Phaser周期

Phaser的值是从0到Integer.MAX_VALUE,每个周期过后该值就会加一,如果到达Integer.MAX_VALUE则会继续从0开始。

如果我们执行多个Phaser周期,则可以重写onAdvance方法:

 protected boolean onAdvance(int phase, int registeredParties) {
  return registeredParties == 0;
 }

onAdvance将会在最后一个arrive()调用的时候被调用,如果这个时候registeredParties为0的话,该Phaser将会调用isTerminated方法结束该Phaser。

如果要实现多周期的情况,我们可以重写这个方法:

protected boolean onAdvance(int phase, int registeredParties) {
    return phase >= iterations || registeredParties == 0;
   }

上面的例子中,如果phase次数超过了指定的iterations次数则就会自动终止。

我们看下实际的例子:

 void startTasks(List<Runnable> tasks, final int iterations) {
  final Phaser phaser = new Phaser() {
   protected boolean onAdvance(int phase, int registeredParties) {
    return phase >= iterations || registeredParties == 0;
   }
  };
  phaser.register();
  for (final Runnable task : tasks) {
   phaser.register();
   new Thread() {
    public void run() {
     do {
      task.run();
      phaser.arriveAndAwaitAdvance();
     } while (!phaser.isTerminated());
    }
   }.start();
  }
  phaser.arriveAndDeregister(); // deregister self, don't wait
 }

上面的例子将会执行iterations次。

本文的例子请参考https://github.com/ddean2009/learn-java-concurrency/tree/master/Phaser

到此这篇关于java多线程之Phaser的使用的文章就介绍到这了,更多相关java多线程Phaser内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot中的@ConfigurationProperties注解解读

    Spring Boot中的@ConfigurationProperties注解解读

    在SpringBoot框架中,@ConfigurationProperties注解是处理外部配置的强大工具,它允许开发者将配置文件中的属性自动映射到Java类的字段上,实现配置的集中管理和类型安全,通过定义配置类并指定前缀,可以将配置文件中的属性绑定到Java对象
    2024-10-10
  • java 反射 动态调用不同类的静态方法(推荐)

    java 反射 动态调用不同类的静态方法(推荐)

    下面小编就为大家带来一篇JAVA 反射 动态调用不同类的静态方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-08-08
  • Java实现文件的归档和解档

    Java实现文件的归档和解档

    这篇文章主要为大家详细介绍了Java实现文件的归档和解档,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-09-09
  • JSON序列化Redis读取出错问题解决方案

    JSON序列化Redis读取出错问题解决方案

    这篇文章主要介绍了JSON序列化Redis读取出错问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • 三步轻松搭建springMVC框架

    三步轻松搭建springMVC框架

    这篇文章主要教大家三步轻松搭建springMVC框架,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • Java中Scanner的用法示例小结

    Java中Scanner的用法示例小结

    有时候我们在编写代码的时候可能会使用输入和输出,那Java也有自己的输入和输出,今天我们来探究一下,对Java Scanner用法相关知识感兴趣的朋友一起看看吧
    2025-04-04
  • 如何应对spring框架的HTTP ERROR 400 Bad Request错误返回问题

    如何应对spring框架的HTTP ERROR 400 Bad Request错

    这篇文章主要介绍了如何应对spring框架的HTTP ERROR 400 Bad Request错误返回问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java设计模式之抽象工厂模式(Abstract Factory)

    Java设计模式之抽象工厂模式(Abstract Factory)

    这篇文章主要为大家详细介绍了Java设计模式之抽象工厂模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Java内存屏障详解

    Java内存屏障详解

    文章主要介绍了内存屏障的必要性,以及在多核处理器中如何通过内存屏障来保证多线程程序的内存可见性和防止指令乱序执行,文章还详细解释了内存屏障的作用、原理以及常见处理器中的重排序类型
    2025-01-01
  • 利用Java实现动态加载数据库

    利用Java实现动态加载数据库

    这篇文章主要为大家详细介绍了一个java小案例,即动态加载数据库信息,文中的示例代码简洁易懂,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-10-10

最新评论