私が Phaser をどのように使用するかについての基本的なアイデアと私が遭遇した問題を含むレポはここにあります: https://github.com/hipy/phaser/tree/master/src
Phaser を使用して、ThreadPools を使用して Dijkstra アルゴリズムをより効率的にすることに取り組んできました。ループを使用して多くの反復を行います。反復ごとに、現在の反復を続行する前に、ThreadPool 内のスレッドが終了するのを待つために Phaser が必要です。
問題が発生しました。Phaser が正しく待機しません。ArriveAndDeregister() を使用すると、各スレッドが完了した後に Phaser が終了状態に入ります。Arrive() を呼び出しても、未到着のパーティの数が減らないため、反復がスタックします。
以下のすべてのコードは、一度呼び出された apply() メソッドで実行されます。
以下のコードは、スレッドが実行するタスクを作成します。
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);
}
}
以下のコードは、for ループの反復ごとに実行されます。この場合、30.000 回の反復があります。
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());
アルゴリズムの一部のコードをスキップして、次のコードが for ループで実行され、スレッドが開始され、スレッドが終了するのを待ちます。
for(int t = 0; t < tasks.length; t++) {
executor.execute(tasks[t]);
}
phaser.arriveAndAwaitAdvance();
出力は次のとおりです。
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
最初のフェーズが実行され、完全な反復が行われます。第二段階は行き詰まる。未到着のパーティーの数は 6 です。3 つの新しいパーティーと、どうやら 3 つの古いパーティーは、phaser.arrive() を呼び出しても到着済みとして登録されませんでした。また、ArriveAndAwaitAdvance() は待機しませんでした。これは、次の反復で 3 ではなく 6 の未到着のパーティがあるためです。
ArrivalAndDeregister() を使用してみましたが、これによりフェーズが終了します (phasecount に大きな負の値があります)。
どうすればこれを解決できますか?フェーズを終了したくはありませんが、反復ごとに到着したパーティーを登録したいと思います。
ありがとう!