One way to cause a set of threads to repeatedly perform actions for a given number of iterations is to override {@code onAdvance}:
{@code}void startTasks(ListIf the main task must later await termination, it may re-register and then execute a similar loop: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 }}
{@code // ... phaser.register(); while (!phaser.isTerminated()) phaser.arriveAndAwaitAdvance();}
Related constructions may be used to await particular phase numbers in contexts where you are sure that the phase will never wrap around {@code Integer.MAX_VALUE}. For example:
{@code}void awaitPhase(Phaser phaser, int phase) int p = phaser.register(); // assumes caller not already registered while (p < phase) { if (phaser.isTerminated()) // ... deal with unexpected termination else p = phaser.arriveAndAwaitAdvance(); } phaser.arriveAndDeregister(); }}
To create a set of {@code n} tasks using a tree of phasers, youcould use code of the following form, assuming a Task class with a constructor accepting a {@code Phaser} that it registers with uponconstruction. After invocation of {@code build(new Task[n], 0, n,new Phaser())}, these tasks could then be started, for example by submitting to a pool:
{@code}void build(Task[] tasks, int lo, int hi, Phaser ph) if (hi - lo > TASKS_PER_PHASER) { for (int i = lo; i < hi; i += TASKS_PER_PHASER) { int j = Math.min(i + TASKS_PER_PHASER, hi); build(tasks, i, j, new Phaser(ph)); } } else { for (int i = lo; i < hi; ++i) tasks[i] = new Task(ph); // assumes new Task(ph) performs ph.register() } }}The best value of {@code TASKS_PER_PHASER} depends mainly onexpected synchronization rates. A value as low as four may be appropriate for extremely small per-phase task bodies (thus high rates), or up to hundreds for extremely large ones.
Implementation notes: This implementation restricts the maximum number of parties to 65535. Attempts to register additional parties result in {@code IllegalStateException}. However, you can and should create tiered phasers to accommodate arbitrarily large sets of participants. @since 1.7 @author Doug Lea
|
|