【问题标题】:How do I find out when the last party fires Phaser.arrive()?我如何知道最后一方何时触发 Phaser.arrive()?
【发布时间】:2011-11-26 06:51:13
【问题描述】:

给定:

Executor executor = ...;
Phaser phaser = new Phaser(n);
for (int i=0; i<n; ++i)
{
  Runnable task = new Runnable()
  {
    public void run()
    {
      phaser.arriveAndDeregister();
      if (lastTask)
        doSomething(this);
    }
  }

  // run tasks using a thread-pool (order is not guaranteed)
  executor.submit(task);
}

我想知道我是否是最后一个触发doSomething() 的任务,这取决于任务的内部状态。我找到了Phaser.onAdvance(int, int),但不清楚在这种情况下如何使用它。

【问题讨论】:

    标签: java concurrency phaser


    【解决方案1】:

    我想不出一个非常优雅的方法来解决这个问题,但是使用 ThreadLocal 和 onAdvance 可以提供帮助。

        final ThreadLocal<Boolean> isLast = new ThreadLocal<Boolean>() {
            public Boolean initialValue() {
                return false;
            }
        };
        final Phaser p = new Phaser(9) {
            public boolean onAdvance(int phase, int registeredParties) {
                isLast.set(true);
                return true;
            }
        };
    

    然后

      public void run()
        {
          phaser.arriveAndDeregister();
          if (isLast.get())
            doSomething(this);
        }
    

    【讨论】:

      【解决方案2】:

      由于您似乎先验知道您有多少任务,因此只需使用单独的AtomicInteger

      int n = 5;
      ExecutorService executor = ...
      final AtomicInteger count = new AtomicInteger (n);
      final Phaser phaser = new Phaser (n);
      for (int i = 0; i < n; ++i) {
          Runnable task = new Runnable () {
              public void run () {
                  phaser.arriveAndDeregister ();
                  if (count.decrementAndGet () == 0) {
                      doSomething (this);
                  }
              }
          };
      
          // run tasks using a thread-pool (order is not guaranteed)
          executor.submit (task);
      }
      

      或者,如果您需要在通知休眠方之前致电 doSomething,只需覆盖 onAdvance 并从那里开始。

      final Phaser phaser = new Phaser (n) {
          protected boolean onAdvance(int phase, int registeredParties) {
              doSomething(this);
      
              return super.onAdvance(phase, registeredParties);
          }
      };
      

      【讨论】:

      • 我不认为你的代码应该检查if (registeredParties == 0),因为onAdvance()保证只有在各方都到达后才会被调用。无论有 0 方或更多方在等待,该事件都应该触发。
      猜你喜欢
      • 2020-06-24
      • 2023-03-04
      • 2021-05-09
      • 1970-01-01
      • 2011-05-27
      • 1970-01-01
      • 2010-09-08
      • 2019-08-09
      • 1970-01-01
      相关资源
      最近更新 更多