0

我有循环,我在哪里下载图像,我需要加载例如 10 个图像并将它们合并到一个图像中。在我的兴趣中,将加载哪些图像。我就是这样做的。我有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 会话永远不会关闭(来自服务器的响应不回来)。这会发生吗?我认为在这种情况下我会遇到一些异常并且坏线程会被中断。正是在我开始循环时发生了这种情况,但在第三张图像上,我通过防火墙关闭了互联网连接。在输出时,我得到损坏的图像,例如网络已关闭并且图像未加载到结束。我错了吗?

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

除了按照@corsiKabarrier.countDown()的建议移动到finally块之外,请确保您的代码完成。在阅读和上设置一些超时:URLawait()

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