A repo with the basic idea of how I use the Phaser and the problem that I run into can be found here: https://github.com/hipy/phaser/tree/master/src
I've been working on making a Dijkstra algorithm more efficient with ThreadPools using a Phaser. I make a lot of iterations with a loop and for each iteration a Phaser is needed to wait for the threads in the ThreadPool to finish before continuing the current iteration.
I've run into a problem, the Phaser does not wait correctly. When I use ArriveAndDeregister() the Phaser enters a termination state after each thread is done. When I call Arrive() the amount of unarrived parties does not decrease and thus the iteration gets stuck.
All code below runs in an apply() method called once.
This code below creates the tasks for the threads to execute.
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool((numberOfThreads));
Phaser phaser = new Phaser();
//Thread class
class ClosestNodeTask implements Runnable {
private int start;
private int end;
private Phaser phaser;
public ClosestNodeTask(int start, int end, Phaser phaser) {
this.start = start;
this.end = end;
this.phaser = phaser;
}
@Override
public void run() {
getNodeShortestDistanced(start, end, phaser); //method calls phaser.arrive() when done
}
}
for (int t = 0; t < numberOfThreads; t++) {
if (nodesModulo > 0 && numberOfThreads == (t + 1)) {
start = nodesPerThread * (t);
end = nodesPerThread * (t + 1) + nodesModulo;
tasks[t] = new ClosestNodeTask(start, end, phaser);
} else {
start = nodesPerThread * t;
end = nodesPerThread * (t + 1);
tasks[t] = new ClosestNodeTask(start, end, phaser);
}
}
The code below is executed for each iteration in a for loop. In this case there are 30.000 iterations:
phaser.register(); //register main thread
for(int t = 0; t < tasks.length; t++) {
phaser.register();
}
System.out.println("Phaser unarrived party size is now: " + phaser.getUnarrivedParties());
Skipping some code for the algorithm the following code is executed in the for loop, starting the threads and waiting for it to finish:
for(int t = 0; t < tasks.length; t++) {
executor.execute(tasks[t]);
}
phaser.arriveAndAwaitAdvance();
The output is as following:
Phasecount: 0
Phaser unarrived party size is now: 3
Task size: 2
Adding: 613 //Next closest node in a sub-group, result of work done in a thread
Adding: 2870
all tasks done
-----------------done-------------
Phasecount: 1
Phaser unarrived party size is now: 6
Task size: 2
Adding: 1
Adding: 2870
The first phase executes, doing the full iteration. The second phase gets stuck. The amount of unarrived parties is 6. 3 new parties and apparently 3 old ones that did not register as arrived even though I called phaser.arrive(). Also the ArriveAndAwaitAdvance() did not wait because in the next iteration there are 6 unarrived parties instead of 3.
I tried using arriveAndDeregister() but this results in a terminated phase(phasecount has a large negative value).
How could I solve this? I don't want to terminate a phase but I do want to register the parties as arrived each iteration.
Thanks!