【问题标题】:Issues multi-threading the loading of thousands of images causing IOException问题多线程加载数千张图像导致 IOException
【发布时间】:2014-12-11 20:12:48
【问题描述】:

我在通过 ForkJoinPool 加载大量图像时遇到问题,我正在使用超线程的 4 核 Intel 进行测试,因此有 8 个逻辑线程。但是,我将池限制为只有 4 个线程。我收到来自 ImageIO 的错误,无法找到图像。

public class LoadImages extends RecursiveAction {
private static final long serialVersionUID = 1L;

//this is an example
private static int threadThreshold = totalImages/totalThreads + 2;

private String[] imgArr;
private int arrStart = 0;
private int arrSize = 0;

public LoadImages(String[] imgs, int start, int size) {
    imgArr = imgs;
    arrSize = size;
    arrStart = start;
}

protected void processImages(){
    BufferedImage img = null;
    for (int i = arrStart; i < arrStart + arrSize; i++) {
        try{
            img = ImageIO.read(new File(imgArr[i]));    
        } catch (IOException | CMMException | NullPointerException e) {
            System.out.println(imgArr[i]);
            e.printStackTrace();
            img = null;
        }

        ...

    }
}

protected void compute() {
    // Check the number of files
    if (arrSize <= threadThreshold) {
        processImages();
        return;
    } else {

        int split = arrSize / 2;

        invokeAll(new LoadImages(imgArr, arrStart, split), new LoadImages(imgArr, arrStart + split, arrSize - split));
    }

}
}

任何关于我做错了什么的见解都会很棒,我注意到只有当我有超过 1700 张图片并且所有图片都超过 5MB 时它才会中断。

这是我从 Java 收到的错误:

javax.imageio.IIOException: Can't create an ImageInputStream!
at javax.imageio.ImageIO.read(Unknown Source)

当我知道文件在那里时。 我将此代码用作指南: https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html

【问题讨论】:

  • 您的第一个错误是在compute() 和invokeall() 中。您应该对第一个 LoadImages 使用 fork(),对第二个 LoadImages 使用 compute()。查看 ForkJoinPool 的 JavaDoc。 invokeAll() 在继续之前等待所有调用的任务完成。
  • @edharned 我明白你的意思,我试过了,实际上是从那里开始的。但是,如果我这样做 loadImg1.fork(); loadImg2.compute(); loadImg1.join();它做同样的事情我错了吗?看看我遵循的示例:docs.oracle.com/javase/tutorial/essential/concurrency/… 无论哪种方式,我仍然会遇到相同的错误。
  • 为了更快的速度,尝试设置ImageIO.useCache(false)。另外,我认为您应该使用 cmets 中提到的IOException 将问题更新为以下答案之一。这很可能是原因。也许您的进程可以拥有的打开文件数量或类似文件数量受到限制?
  • 我将 IOException 添加到 titlevand 我还将尝试将 useCache 设置为 false,看看是否有帮助。
  • 我仍然认为使用带有线程池的队列会更容易(生产者/消费者)。使用 FJ 进行异步处理有局限性。你可以只计算你需要的任务数量,然后 fork() 那么多,因为你不等待完成。您遇到的错误可能是@Wes Cumberland 在下面所说的。看来您正在将并发性与并行性混为一谈。

标签: java multithreading javax.imageio forkjoinpool work-stealing


【解决方案1】:

似乎有点随机。我的猜测是它可能只是硬件或操作系统错误。假设这是一个缩放问题,我对您的 1700 多张图像的建议是,您最好将其设置在云端的某个地方 - 可以节省大量时间和头痛

【讨论】:

  • 我同意这肯定是硬件/io 硬盘问题。但是,我尝试在 try/catch 周围放置一个 while 循环,我得到了一个无限循环。似乎一旦它每次都失败一次就无法访问文件……但是如果我关闭程序并再次运行它,一切正常……太奇怪了!但是,如果我等一天重新运行,我会遇到同样的问题,然后第二次就可以了。但是,如果我将图像放在 NAS 上,例如 Thecus(当前备份存储)。无论我运行程序多少次,我都会让它失败
【解决方案2】:

在我看来,它在内部创建 ImageInputStream 时出现 ImageIO 错误。您是否尝试使用 ImageInputStream 读取图像?喜欢:

InputStream is = new FileInputStream("path");
ImageInputStream iis = ImageIO.createImageInputStream(is);
BufferedImage bufImage = ImageIO.read(iis);

【讨论】:

  • 刚刚尝试过,似乎仍然是一个相关问题:java.io.FileNotFoundException: C:\jpg\IMG_7734.jpg (系统无法打开文件) at java.io.FileInputStream.open( Native Method) at java.io.FileInputStream.(Unknown Source) at java.io.FileInputStream.(Unknown Source) 并且文件肯定在那里
  • 您是否尝试过同步阅读?总是相同的文件还是随机的?
  • 我不确定我理解你的意思,该数组是在与 walkFileTree 不同的类中构建的。我会放什么同步?输入流?
【解决方案3】:

如果您检查ImageIO.read(File)ImageIO.read(ImageInputStream) 的源代码,您会看到ImageIO 重用了ImageReader 的实例,而this article 表示ImageReader 不是线程安全的。您可能必须创建自己的ImageReaders 以在单独的线程中使用。

您还应该衡量这种多线程 IO 策略真正为您带来的收益。如果您试图从旋转的硬盘驱动器中提取大量图像数据,您的进程可能会受到 I/O 限制,并且并行加载不会给您带来太多好处。

【讨论】:

  • 它实际上节省了大量时间。因为 SSD 似乎永远不会出现故障(只有旋转磁盘驱动器,这让我认为这可能是硬件问题)。用 4 个线程加载大约 5gb 的图像确实需要大约 1/3 - 1/4 的时间。我也觉得不是 ImageIO 导致了问题,因为如果我使用 InputStream 它仍然失败,我会尝试在每个线程中发布一个新的阅读器,看看是否能解决问题。谢谢!
  • 这里没有骰子,似乎是一个相关问题。但是,在阅读此线程:stackoverflow.com/a/26300361/3015634 时,结论似乎是 Java 对 ImageIO 的主要关注不是线程安全,但似乎仍然如此。
  • ImageReaders 不是线程安全的,并不意味着您不能在多线程环境中使用它们。不幸的是,这是一个常见的误解。它的意思是您不能在多个线程之间共享ImageReader 的单个实例。在多个线程中使用ImageIO.read() 是安全的。
猜你喜欢
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-18
  • 1970-01-01
相关资源
最近更新 更多