2012-03-09 7 views
1

大規模なデータグラフを取得するために再帰的にサーバーを呼び出す必要があるJavaクライアントがあり、約1000回の呼び出しが必要です。私はサーバーを制御することができず、これは時間が重大なクラッシュリカバリのシナリオに必要です。Blocking I/Oを使用するRecursiveAction/ForkJoinPool

私の問題は、すべての呼び出しが完了するまでブロックするために元のスレッドが必要なことです。

java.util.concurrentのRecursiveActionとForkJoinPoolの抽象概念は、CPU並列処理用に設計されており、I/Oのブロックを禁止する点を除いて、私が必要とするものです。

したがって、すべての呼び出しが完了するまで、スレッドの開始をブロックして、再帰的ネットワーク呼び出しを実装する最良の方法は何ですか?

追加のコンテキスト情報:

  • 私は、サーバーを変更することはできません。
  • サーバーは、この種の重い照会を許可し、サポートしています。
  • 私は同時のネットワークコールの数を10-30のように制限します。
  • ディスク上のデータをキャッシュすることは実現できません。

追加の考え:ThreadPoolExecutorと組み合わせて、単相フェイザーが適切でしょうか?コールタスクはPhaser.register()を呼び出し、コールを行い、子タスクを送信してPhaser.arrive()を呼び出します。開始スレッドはPhaser.awaitAdvance(1)を呼び出します。これが最も適切なアプローチでしょうか?

答えて

3

JDK1.7のフェイザーを使用してうまくいきました。私が使用したパターンは、次のようなものでした:

private void loadGraphFromServer() { 
    final Phaser phaser = new Phaser(1); // "1" registers the calling thread 
    for (final Item item : getDataListFromServer()) { 
     phaser.register(); 
     executorService.submit(new Runnable() { 
      public void run() { 
       try { 
        getMoreDataFromServer(item.getSomeId()); 
        // more nested loops/tasks/calls here... 
       } 
       finally { 
        phaser.arrive(); 
       } 
      } 
     }); 
    } 
    phaser.arriveAndAwaitAdvance(); // blocks until all tasks are complete 
} 
0

私は固定サイズのエクゼキュータプールを使用しようとします。最大サイズを10〜30スレッドに設定することができます.1000リクエストでは1リクエストを追加し、2リクエストを追加すると1リクエストを追加します。これらのリクエストがすべてshutdown()とawaitTerminationで完了するまで待つことができます()

+0

ありがとうございますが、私はシャットダウン/ awaitTerminationを使用できません。なぜなら、開始スレッドは最後のタスクがいつ提出されたかを知らないからです。 – Paul

+0

各タスクは、作成したタスクを待つことができます。テールの最適化を行うことができます。つまり、最後のタスクが実行される場合は別のタスクを作成しないでください。 –

+2

しかし、私は何かが欠けていない限り、スレッドを使い果たしてしまいます。 – Paul