Java:jsr166y Phaser的教程/解释

这个问题是两年前提出的,但它提到的资源要么不是很有用(恕我直言),要么链接不再有效。

必须有一些很好的教程才能理解Phaser 。 我已经阅读了javadoc,但是我的眼睛茫然,因为为了真正理解javadoc你必须知道如何使用这些类。

有人有什么建议吗?

对于Phaser,我已经回答了几个问题。 看到它们可能有助于理解它们的应用。 它们在底部相连。 但要了解Phaser的作用以及为什么它有用,重要的是要知道它解决了什么。

以下是CountdownLatch和CyclicBarrier的属性

注意:

  • 聚会的数量是说不同线程的另一种方式
  • 不可重用意味着您必须在重新使用之前创建屏障的新实例
  • 如果线程可以到达并且在不等待其他人的情况下继续工作或者可以等待所有线程完成,则可以推进屏障

CountdownLatch

  • 固定数量的政党
  • 不可恢复
  • 可推进(查看latch.countDown(); 升级的 latch.await(); 必须等待

的CyclicBarrier

  • 固定数量的政党
  • 可重复使用
  • 不可推进

因此CountdownLatch不可重用,您必须每次都创建一个新实例,但是可以使用。 可以重复使用CylicBarrier,但所有线程必须等待每一方到达屏障。

移相器

  • 动态党派数量
  • 可重复使用
  • 推进的

当一个线程想要被Phaser知道时,当线程到达屏障时,它们会调用phaser.arrive() 它们会调用phaser.arrive() ,这里它是可推进的 。 如果线程想要等待所有已注册的任务完成phaser.arriveAndAwaitAdvance()

还有一个阶段的概念,其中线程可以在完成其他可能尚未完成的操作时等待。 一旦所有线程到达移相器的障碍,就会创建一个新阶段(增量为1)。

你可以看看我的其他答案,也许它会有所帮助:

Java ExecutorService:awaitTermination所有递归创建的任务

灵活的CountDownLatch?

至少对于Phaser来说,我认为JavaDoc提供了一个相当清晰的解释。 这是一个用于同步一批线程的类,在这种意义上,您可以使用Phaser注册批处理中的每个线程,然后使用Phaser阻止它们直到批处理中的每个线程都通知Phaser ,此时任何被阻塞的线程都将开始执行。 该等待/通知周期可以根据需要/要求一遍又一遍地重复。

他们的示例代码给出了一个合理的例子(尽管我非常不喜欢他们的2字符缩进样式):

 void runTasks(List 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(); } 

这将设置一个注册计数为tasks.size() + 1Phaser ,并为每个任务创建一个新的Thread ,它将阻塞直到Phaser的下一个tasks.size() + 1tasks.size() + 1到达的时间已被记录)然后运行其相关的任务。 创建的每个Thread也会立即启动,因此Phaser会在记录tasks.size()到达的情况下退出循环。

phaser.arriveAndDeregister()的最后调用将记录最终到达,并减少注册计数,使其现在等于tasks.size() 。 这会导致Phaser前进,这实际上允许所有任务同时开始运行。 这可以通过以下方式重复:

 void runTasks(List 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() { while (true) { phaser.arriveAndAwaitAdvance(); // await all creation task.run(); } } }.start(); } // allow threads to start and deregister self phaser.arriveAndDeregister(); } 

…这与以前相同,只是添加了一个循环,导致任务重复运行。 因为每次迭代都会调用phaser.arriveAndAwaitAdvance() ,所以任务线程的执行将被同步,以便task-0不会开始第二次迭代,直到每个其他任务完成其第一次迭代并通知Phaser已准备好开始其第二次迭代迭代。

如果您运行的任务在执行时花费的时间差异很大,并且您希望确保更快的线程不会与较慢的线程不同步,则这可能很有用。

对于可能的实际应用程序,请考虑运行单独的图形和物理线程的游戏。 如果图形线程卡在第6帧上,您不希望拥有第100帧的物理线程计算数据,并且使用Phaser是确保图形和物理线程始终在同一帧上工作的一种可能方法。同时(并且如果一个线程明显慢于另一个线程,则更快的线程优雅地产生CPU资源,以便更慢的线程可以更快地赶上)。

Phaser在CyclicBarrier和CountDownLatch的function上有些相似,但它提供了比两者更多的灵活性。

在CyclicBarrier中,我们曾经在构造函数中注册各方,但Phaser为我们提供了随时注册和取消注册方的灵活性。 对于注册方,我们可以使用以下任何一种方式 –

  • 建设者
  • 注册,或
  • bulkRegister

对于deRegistering派对,我们可能会使用 –

  • 到达和取消注册,或

注册 –添加/注册此移相器的新未命名方。 它回来了

  • 该注册所适用的到达阶段号。
  • 如果移相器已终止,则值为负,注册无效。

如果onAdvance()方法的调用正在进行中,则返回此方法之前可能会等待其完成。 如果此移相器具有父级,并且此移相器没有注册方,则此子移相器也在其父级中注册。
用于演示Phaser使用的程序>

 import java.util.concurrent.Phaser; public class PhaserTest { public static void main(String[] args) { /*Creates a new phaser with 1 registered unArrived parties * and initial phase number is 0 */ Phaser phaser=new Phaser(1); System.out.println("new phaser with 1 registered unArrived parties" + " created and initial phase number is 0 "); //Create 3 threads Thread thread1=new Thread(new MyRunnable(phaser,"first"),"Thread-1"); Thread thread2=new Thread(new MyRunnable(phaser,"second"),"Thread-2"); Thread thread3=new Thread(new MyRunnable(phaser,"third"),"Thread-3"); System.out.println("\n--------Phaser has started---------------"); //Start 3 threads thread1.start(); thread2.start(); thread3.start(); //get current phase int currentPhase=phaser.getPhase(); /*arriveAndAwaitAdvance() will cause thread to wait until current phase * has been completed ie until all registered threads * call arriveAndAwaitAdvance() */ phaser.arriveAndAwaitAdvance(); System.out.println("------Phase-"+currentPhase+" has been COMPLETED----------"); //------NEXT PHASE BEGINS------ currentPhase=phaser.getPhase(); phaser.arriveAndAwaitAdvance(); System.out.println("------Phase-"+currentPhase+" has been COMPLETED----------"); /* current thread Arrives and deRegisters from phaser. * DeRegistration reduces the number of parties that may * be required to advance in future phases. */ phaser.arriveAndDeregister(); //check whether phaser has been terminated or not. if(phaser.isTerminated()) System.out.println("\nPhaser has been terminated"); } } class MyRunnable implements Runnable{ Phaser phaser; MyRunnable(Phaser phaser,String name){ this.phaser=phaser; this.phaser.register(); //Registers/Add a new unArrived party to this phaser. System.out.println(name +" - New unarrived party has " + "been registered with phaser"); } @Override public void run() { System.out.println(Thread.currentThread().getName() + " - party has arrived and is working in " + "Phase-"+phaser.getPhase()); phaser.arriveAndAwaitAdvance(); //Sleep has been used for formatting output try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //------NEXT PHASE BEGINS------ System.out.println(Thread.currentThread().getName() + " - party has arrived and is working in " + "Phase-"+phaser.getPhase()); phaser.arriveAndAwaitAdvance(); phaser.arriveAndDeregister(); } 

}

bulkRegister –为此移相器添加新的未获得多方的各方。 它回来了

  • 该注册所适用的到达阶段号。
  • 如果移相器已终止,则值为负,注册无效。

如果onAdvance()方法的调用正在进行中,则返回此方法之前可能会等待其完成。

到达和取消注册 –当前主题(派对)从移相器到达和退出。 DeRegistration减少了将来可能需要进入下一阶段的各方数量。

如果此移相器具有父级 ,并且此移相器没有注册方,则此子移相器也在其父级中注册。 计划展示父母和子女Phaser

 import java.util.concurrent.Phaser; public class PhaserParentChildTest { public static void main(String[] args) { /* * Creates a new phaser with no registered unArrived parties. */ Phaser parentPhaser = new Phaser(); /* * Creates a new phaser with the given parent & * no registered unArrived parties. */ Phaser childPhaser = new Phaser(parentPhaser,0); childPhaser.register(); System.out.println("parentPhaser isTerminated : "+parentPhaser.isTerminated()); System.out.println("childPhaser isTerminated : "+childPhaser.isTerminated()); childPhaser.arriveAndDeregister(); System.out.println("\n--childPhaser has called arriveAndDeregister()-- \n"); System.out.println("parentPhaser isTerminated : "+parentPhaser.isTerminated()); System.out.println("childPhaser isTerminated : "+childPhaser.isTerminated()); } } 

有关Phaser的更多信息, 请访问http://www.javamadesoeasy.com/2015/03/phaser-in-java_21.html