2

リモートサーバーに画像をアップロードするために以下のコードを使用しています。以下を使用すると、すべての画像がリモートサーバーに同時にアップロードされます。

List<Future<String>> futureList = new ArrayList<Future<String>>();
ExecutorService execService = Executors.newFixedThreadPool(Images.size());
for (IImage image : Images) { 
  try {
    //execService.execute(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
    singleFuture = execService.submit(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
    //Log.d("","singleFuture -------"+singleFuture.get());
    futureList.add(singleFuture);
    Log.d("","futureList Size:"+futureList.size());
  } catch(Exception e){
    execService.shutdown();
  }

以下のコードを使用するたびに

   singleFuture = execService.submit(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
//Log.d("","singleFuture -------"+singleFuture.get());
    futureList.add(singleFuture);

すべての将来のオブジェクトを、runnable から戻るとすぐに futurelist に追加します (すべての画像のアップロードが完了するまで runnable で待機しません (バックグラウンドのアップロード処理が進行中です))。

しかし、上記のコードの行の下でコメントを外すたびに、すべての画像のアップロードが成功した後、実行可能から返されます。

singleFuture = execService.submit(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
Log.d("","singleFuture -------"+singleFuture.get());
futureList.add(singleFuture);

私のコードに何か問題がありますか?一度にリモートサーバー接続を増やしても大丈夫ですか?またはサーバーに負荷がかかっていますか?並列プログラミングJavaを使用して画像をアップロードする方法?ガイダンスを教えてください?

submit()execute()関数は同じ効果がありますか?

4

2 に答える 2

3

あなたが呼び出す singleFuture.get()ときは、操作が完了するのを待っています。したがって、このステートメントが結果を返すまで、ループは次のステートメントの実行を続行しません。

最初のループでタスクを送信する必要があり、その後、別のループでfuture.get()リストの結果を反復して非同期にする必要があります

@andersojの回答から;

プール サイズは、CPU コアに関連するものである必要があります。手元にある画像の数ではありません。2 コアの CPU を使用している場合、画像のアップロード時間の係数は 5 (私の推測による係数) であるとします。

POOL_SIZE = NUM​​_OF_CPU_CORE*係数;

于 2011-02-25T10:32:04.673 に答える
2

submit()タスクをキューに追加し、 を返しますFutureexecute()を返しませんFuture。こちらもご覧ください。内部で発生する追加の管理の副作用として、観察されるさまざまな順序が発生する可能性がありsubmit()、おそらく無関係です。(ただし、@ fmucarの回答を参照してください...)

あなたの質問が何であるか正確にはわかりません...

アップロードする画像の数に基づいてスレッド プールのサイズを設定することは、実際には意味がありません。いくつかの TCP ストリームを供給し続けようとしているだけなので、おそらく少数のスレッドで十分です。画像のリストが大きい場合、画像ごとに 1 つのスレッドでは何も得られません。

Futuresアップロードがいつ完了するかを知るためだけに収集する場合は、次のいずれかを検討してください。

追加するために編集: 良いキャッチ、@fmucar、.get()ロガー行での呼び出しは連続性を強制するため、スレッドプールは無駄です。

invokeAll() の例

ここにinvokeAll()例を示します。コードと完全に一致するかどうかはわかりません。

final int poolSize = ...;  // see fmucar's answer
final ExecutorService execService = Executors.newFixedThreadPool(poolSize);
final List<Callable<>> uploadTasks = new ArrayList<Callable<>>();

for (final IImage image : Images) { 
   // maybe I got this wrong?  Can't quite parse your code.
   Callable<String> uTask = new uploadImages(image.getDataPath(),image.getDisplayName());
   uploadTasks.add(uTask);
}
// this thread will block here until all the tasks complete
final List<Future<String>> futureList = execService.invokeAll();
// or you can toss the result entirely if the futures don't matter.    
于 2011-02-25T10:18:53.177 に答える