Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 发布多线程加载数千个图像,导致IOException_Java_Multithreading_Javax.imageio_Forkjoinpool_Work Stealing - Fatal编程技术网

Java 发布多线程加载数千个图像,导致IOException

Java 发布多线程加载数千个图像,导致IOException,java,multithreading,javax.imageio,forkjoinpool,work-stealing,Java,Multithreading,Javax.imageio,Forkjoinpool,Work Stealing,我在通过ForkJoinPool加载大量图像时遇到问题,我正在一个4核Intel上进行测试,该Intel具有超线程so 8逻辑线程。但是,我将池限制为仅4个线程。我收到来自ImageIO的错误,无法找到图像 public class LoadImages extends RecursiveAction { private static final long serialVersionUID = 1L; //this is an example private static int thread

我在通过ForkJoinPool加载大量图像时遇到问题,我正在一个4核Intel上进行测试,该Intel具有超线程so 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多幅图像的建议是,您最好在云上的某个地方设置它-如果您去检查源代码中的
ImageIO.read(文件)
ImageIO.read(ImageInputStream),可以节省大量时间和麻烦
您可以看到,
ImageIO
重用了
ImageReader
的实例,并指出
ImageReader
不是线程安全的。您可能需要创建自己的
ImageReaders
,以便在单独的线程中使用


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

在我看来,当它在内部创建ImageInputStream时,似乎是一个ImageIO错误。您是否尝试使用ImageInputStream读取图像?比如:

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

我同意这肯定是硬件/io硬盘的问题。然而,我试着在try/catch上做一个while循环,结果得到了一个无止境的循环。似乎一旦它无法访问文件,每次都会失败一次。。。但是如果我关闭程序,在一切正常的情况下再次运行它。。。真奇怪!但是如果我等一天再运行,我会遇到同样的问题,然后它第二次运行。但是,如果我将映像放置在NAS上,如Thecus(当前备份存储)。我可以让它每次都失败,不管我运行程序多少次,它实际上节省了很多时间。因为SSD似乎从未出现故障(只有旋转的磁盘驱动器,这让我觉得可能是硬件问题)。用4个线程加载大约5gb的图像确实需要1/3-1/4的时间。我也觉得这不是ImageIO造成的问题,因为如果我使用InputStream,它仍然失败,我将尝试在每个线程中发出一个新的读取器,看看这是否解决了问题。谢谢这里没有骰子,似乎是一个相关的问题。然而,在阅读本文时:结论似乎是Java对ImageIO的主要关注点不是线程安全,但它似乎仍然是。ImageReader的线程安全性不高并不意味着不能在多线程环境中使用它们。不幸的是,这是一个常见的误解。。这意味着不能在多个线程之间共享
ImageReader
的单个实例。从多个线程使用
ImageIO.read()
是安全的。刚刚尝试过,这似乎仍然是一个相关的问题:java.io.FileNotFoundException:C:\jpg\IMG_7734.jpg(系统无法打开该文件)在java.io.FileInputStream.open(本机方法)在java.io.FileInputStream。(未知源代码)在java.io.FileInputStream。(未知源代码)文件肯定在那里。你是否尝试同步读取?它总是指向相同的文件还是随机的?我不确定我是否理解你的意思,数组是在不同于walkFileTree的类中构建的。我应该把它放在什么地方?InputStream?您的第一个错误是在compute()和invokeall()中。第一个LoadImages应该使用fork(),第二个LoadImages应该使用compute()。查看用于ForkJoinPool的JavaDoc。invokeAll()等待所有调用的任务完成,然后再继续。@edharned我明白你的意思了,我试过了,实际上是从那里开始的。但是如果我加载img1.fork();loadImg2.compute();loadImg1.join();它也做同样的事我错了吗?看看我下面的例子:无论哪种方式,我仍然会得到相同的错误。为了更快,请尝试设置
ImageIO.useCache(false)
。此外,我认为您应该使用下面答案之一的注释中提到的
IOException
更新问题。这很可能就是原因。也许您的进程可以有多少打开的文件或类似的文件达到了限制?我在标题中添加了IOException,并尝试将useCache设置为false,看看是否有帮助。我仍然认为使用带有线程池的队列会更容易(生产者/消费者)。使用FJ进行异步处理有限制。你可以直接计算你需要的任务数量,因为你不需要等待完成。您所得到的错误可能是@Wes Cumberland在下面所说的。似乎您将并发性与并行性混为一谈。
InputStream is = new FileInputStream("path");
ImageInputStream iis = ImageIO.createImageInputStream(is);
BufferedImage bufImage = ImageIO.read(iis);