0

画像をダウンロードするサイクルがあります。たとえば、10枚の画像を読み込んで、1つの画像にマージする必要があります。私の興味では、どの画像がすべてロードされますか。これが私がそれをする方法です。スレッド数をexecutor制限する必要CountDownLatchがあり、すべての画像が読み込まれるまで待機するバリアがあります。

CountDownLatch barrier = new CountDownLatch(images.size());
private static ExecutorService executorService = Executors.newFixedThreadPool(MAX_THREAD_POOL);

for (Image image : images) {
    executorService.execute(new ImageRunnable(image, barrier));
}
    barrier.await();

ImageRunnable私はこのような画像をダウンロードします。グーグル静的地図から。

String url ="my url"
try {
    URL target = new URL(url);
    ImageIO.read(target);
    barrier.countDown();
    //exaggerated logic
} catch (IOException e) {
    System.out.println("Can not load image, " + e);
}

executor他の人は、すべてのスレッドがビジーになり、すべてのスレッドがポイントを取得するまで待機するため、アルゴリズムが終了しない場合にケースを取得できると私に言いましたbarrier.await()(デッドロック)。呼び出されてImageIO.read(target)接続は確立されますが、HTTPセッションが閉じられることはありません(サーバーからの応答が返されません)。これは起こり得ますか?この場合、いくつかの例外が発生し、不良スレッドが中断されると思いました。まさにそれは私がサイクルを開始したときに起こりますが、3番目の画像でファイアウォールによるインターネット接続を閉じます。出力時に、ネットワークが閉じられ、画像が最後まで読み込まれなかったように、画像が壊れます。私が間違っている?

4

3 に答える 3

3

懸念は、例外をスローし、ラッチをカウントダウンしない可能性があることです。

私はこれを行うことを検討します:

String url ="my url"
try {
    URL target = new URL(url);
    ImageIO.read(target);
} catch (IOException e) {
    System.out.println("Can not load image, " + e);
    throw e;
} finally {
    barrier.countDown();
}

例外をスローして、問題に遭遇し、完了できない可能性があることを世界に知らせます (問題から回復できないことはわかっています) が、少なくとも障壁は低くなります。デッドロックよりも例外に対処する必要があります。

于 2012-08-17T18:19:28.693 に答える
1

私のコメントを具体化するために:

CompletionService<Image> service = new ExecutorCompletionService<Image>(
  Executors.newFixedThreadPool(nThreads));
for (Image image : images) {
  service.submit(new ImageRunnable(image), image);
}
try {
  for (int i = 0; i < images.size(); i++) {
    service.take();
  }
} catch (InterruptedException e) {
  // someone wants this thread to cancel peacefully; either exit the thread
  // or at a bare minimum do this to pass the interruption up
  Thread.currentThread().interrupt();
}

そこには。それでおしまい。

HTTP 接続でタイムアウトを強制することを懸念している場合は、私の迅速で汚い調査で次のようなことが示唆されています...

URL target = // whatever;
URLConnection connection = target.openConnection();
connection.setReadTimeout(timeoutInMilliseconds);
InputStream stream;
try {
  stream = connection.getInputStream();
  return ImageIO.read(stream);
} finally {
  if (stream != null) { stream.close(); } 
}
于 2012-08-17T18:45:23.113 に答える
0

@corsiKaによって提案されたようにブロックに移動barrier.countDown()することは別として、コードが必ず終了するようにしてください。読み取り時とオン時にタイムアウトを設定します。finallyURLawait()

barrier.await(1, TimeUnit.MINUTES);
于 2012-08-17T18:22:54.243 に答える