2

オブジェクトを返すサービスに取り組んでいList<Response>ます。

応答を作成できるオブジェクトは2種類あります。1つは内部データからコンテンツを入力し、もう1つはサービスにアクセスしてデータを取得します。

for(Item item : items){
   if(item is external){
     call service and get result and populate Response and add to List
   }

   if(item is internal)
   {
     populate response object and add to list
   }
}

現在のimplは手続き型でブロッキングです。私が欲しいのは、アイテムが外部である場合に呼び出しを実行し、リスト内の次のアイテムに進むような非ブロッキング設計です。次に、ループが完了すると、すべてが終了するのを待つことができます。

これを行うための良いアプローチは何でしょうか?また、責任ごとに個別のクラスを作成することも検討しています。

編集:導入する理由は、レイテンシーヒットを減らすためです。

4

3 に答える 3

5

ExecutorCompletionService(送信されたタスクを記憶するコールバックを備えたスレッドプール)は間抜けなgitのようです:

CompletionService<Response> executorService = 
    new ExecutorCompletionService<>(Executors.newFixedThreadPool(10));
int totalExternal = 0;

for(Item item : items){
    if(item is external){
        executorService.submit(externalCall(item));
        ++totalExternal;
    }

    if(item is internal){
        populate response object and add to list
    }
}

for (int i = 0; i < totalExternal; ++totalExternal) {
    addAsynchResultToResponseList(executorService.take().get());
}

わかりexternalCall(item)やすくするために、次のように定義されています。

Callable<Response> externalCall(Item item) {
  return new Callable<Response>() {
    //...
  }
}

明らかに、非同期にすると、結果リストは任意の順序になる可能性があります。


別のアプローチは、通常を使用しExecutorService、中間を使用することList<Future<Response>>です。秘訣は、AsyncResultラッパーを使用して内部応答をラップすることFutureです(ラッパーを使用して、すぐに実行され、渡された値を返します)。

List<Future<Response>> futures = new ArrayList<>();
for(Item item : items){
    if(item is external){
        futures.add(executorService.submit(externalCall(item)));
    }

    if(item is internal){
        futures.add(new AsyncResult(synchResponse));
    }
}

これで、を簡単に繰り返すことができますfuturesAsyncResult値は作成時にすでにコンピューターであったため、すぐに戻ります(synchResponse)。Futureただし、スレッドプールからsが返されるのを待つ必要があります。

Future.get()これにより、元の例外を取得できることを忘れないでください。また、Futureリスト内のsの順序は元のアイテムの順序と同じであるため、n番目Futureが失敗した場合は、itemsリスト内のn番目のアイテムが原因でした。

于 2012-11-21T19:38:29.880 に答える
1

私がすることは、すべての操作をCallablesでラップし、それらをに送信し、返されたsをリストExecutorServiceに格納することです。Future

次に、すべてが終了したら、結果のリストをメインスレッドに入力します。

于 2012-11-21T19:32:00.770 に答える
0

アイテムが外部にあるときに物事を続けるために、操作call serviceはある種の非同期アクティビティを開始する必要があります(たとえば、ThreadまたはRunnableある種のに送信されますExecutor)。get resultこのアクティビティには、完了後にタスクの最後の部分を実行できるように、コールバックメカニズムが必要ですpopulate Response and add to List

アクセスを同期するListか、すべてのアクセスがシングルスレッドになるように調整する必要があります。

于 2012-11-21T19:37:49.557 に答える