Java ImageIO已同步

Java ImageIO已同步,java,synchronization,javax.imageio,Java,Synchronization,Javax.imageio,我有一个web应用程序,用户可以在其中上传图像。我们通过ImageIO.read()验证图像数据,并在将结果BuffereImage保存到磁盘之前对其执行一些简单的转换 在执行负载测试时,我们意识到当许多请求同时进入时,它们会在ImageIO.read()调用中被阻止。深入挖掘,我们注意到JPEGImageReader是同步的,一次只创建一个BuffereImage 还有其他人见过这个吗?我已经在谷歌上搜索了几天,还没有遇到其他人有这个问题,所以可能我做错了什么。我想不出任何合乎逻辑的理由来解释

我有一个web应用程序,用户可以在其中上传图像。我们通过ImageIO.read()验证图像数据,并在将结果BuffereImage保存到磁盘之前对其执行一些简单的转换

在执行负载测试时,我们意识到当许多请求同时进入时,它们会在ImageIO.read()调用中被阻止。深入挖掘,我们注意到JPEGImageReader是同步的,一次只创建一个BuffereImage

还有其他人见过这个吗?我已经在谷歌上搜索了几天,还没有遇到其他人有这个问题,所以可能我做错了什么。我想不出任何合乎逻辑的理由来解释为什么会这样。这似乎与无法为某个内存泄漏问题创建每张图像的单个读者和作者有关,但对我来说,这一解释似乎相当单薄

编辑:是一个性能工具,它可以分解耗时太长的内容。我相信这是由于所有线程都在等待同步锁,source

编辑:JAI库本来可以工作,但OpenJDK已经取消了对其关键部分的支持,明确地说是JPEG编解码器

解决方案:考虑到我花了大量时间试图找到替代解决方案,但未能找到,我的最佳解决方案是根据请求异步处理图像。因此,当请求进来时,原始图像数据被存储为假定有效的图像;然后,请求线程之外的异步进程将一次处理一个映像。由于ImageIO库的同步性,尝试一次执行多个操作没有任何好处。由于库不是同步的,只是效率低下,因此可以并行处理这些图像


虽然异步处理会增加一定程度的复杂性,但就修改图像而言,这可能是一个好主意。不起作用的是我们不能在每个请求中处理原始图像,这意味着我们的系统必须假设每个图像都是有效的图像数据。当异步处理器开始处理图像时,如果数据不正确,系统可能会出现不一致。

编辑:首先,haraldK的答案是正确的,而我原来的答案是错误的。但不能删除,只有编辑过的OP才能重新分配勾号

ThreadLock机制用于阻止线程从自己的读卡器访问不同的读卡器,而不是阻止线程独立于其他线程并与其他线程同时访问自己的读卡器

因此,ImageIO的JPEGImageReader应该可以异步工作

在执行负载测试时,我们意识到当许多请求同时进入时,它们会在ImageIO.read()调用中被阻止。深入挖掘,我们注意到JPEGImageReader是同步的,一次只创建一个BuffereImage

还有其他人见过这个吗

正如我在评论部分提到的:从性能分析来看,这看起来像是OpenJDK(lcms)的颜色管理系统中的一个性能问题,因为颜色转换不应该花费这么长时间。我猜,在无法进一步调试的情况下,这个问题会使解码(看起来)同步,即使ImageIO能够并行解码

这是一个SSCCE,它显示ImageIO完全能够同时解码多个图像

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.stream.ImageInputStream;
import java.io.File;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

class MultipleJPEGDecoding {
    private static int threads = Runtime.getRuntime().availableProcessors();
    private static ExecutorService executorService = Executors.newFixedThreadPool(threads * 4);

    public static void main(final String[] args) throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            final int index = i;

            executorService.submit(new Runnable() {
                public void run() {
                    try {
                        ImageInputStream stream = ImageIO.createImageInputStream(new File(args[index % args.length]));
                        try {
                            Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
                            if (!readers.hasNext()) {
                                System.err.println("No reader!");
                                return;
                            }

                            ImageReader reader = readers.next();
                            reader.setInput(stream);
                            reader.addIIOReadProgressListener(new ProgressListener(index));

                            try {
                                reader.read(0);
                            }
                            finally {
                                reader.dispose();
                            }
                        }
                        finally {
                            stream.close();
                        }
                    }
                    catch (Exception e) {
                        System.err.printf("Error reading %d\n", index);
                        e.printStackTrace();
                    }
                }
            });
        }

        executorService.shutdown();
    }

    static class ProgressListener implements IIOReadProgressListener {
        final static AtomicInteger simultaneous = new AtomicInteger(0);

        final int index;
        int nextProgress = 25;

        public ProgressListener(int index) {
            this.index = index;
        }

        public void imageStarted(ImageReader source, int imageIndex) {
            int inProgress = simultaneous.incrementAndGet();
            System.err.printf("Started reading image %d (now decoding %d images simultaneous)...\n", index, inProgress);
        }

        public void imageComplete(ImageReader source) {
            int inProgress = simultaneous.decrementAndGet();
            System.err.printf("Done reading image %d%s.\n", index, inProgress > 0 ? String.format(" (still decoding %d other images)", inProgress) : "");
        }

        public void imageProgress(ImageReader source, float percentageDone) {
            if (percentageDone > nextProgress) {
                int inProgress = simultaneous.get();
                System.err.printf("Progress on image %d (now decoding %d images simultaneous)...\n", index, inProgress);
                nextProgress += 25;
            }
        }

        public void sequenceStarted(ImageReader source, int minIndex) {
        }

        public void sequenceComplete(ImageReader source) {
        }

        public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {
        }

        public void thumbnailProgress(ImageReader source, float percentageDone) {
        }

        public void thumbnailComplete(ImageReader source) {
        }

        public void readAborted(ImageReader source) {
        }
    }
}
[……]


您正在运行多个线程吗?您是说类上的多个
JPEGImageReader
实例正在序列化(即单线程)?你是如何确定情况是这样的?如果是这样的话,那么它们都在锁定/等待的监视器在哪里?它肯定是多线程的,因为它们在Tomcat中是单独的请求。我开始相信ImageIO只是在引擎盖下创建了一个底层JPEGImageReader。请参阅:。我们99%确信这是正在发生的事情,因为当我们注释掉创建BuffereImage并进行转换的部分,并将InputStream内容保存到磁盘时,CPU实际上正在被征税。否则,它们在加载时的使用率约为5%。听起来您需要在ImageIO中深入一层,使用创建读卡器的方法,而不是方便的方法。直接使用读卡器/写卡器的问题是,我实际上需要ImageIO中的一些方便实用程序。我希望能够抛出一个输入流,并得到一个“验证”的图像。如果我降低,我将被锁定为一种格式,例如JPEG,或者我将重写库的大部分。从您的分析数据(可能不完整)来看,问题似乎是OpenJDKs颜色管理(LCMS)中的一个严重性能问题。我认为这个CMS不用于Sun/Oracle虚拟机。你试过其他虚拟机吗?JPEGImageReader在内部使用每个实例的同步这一事实不应导致您得出ImageIO不能同时处理多个图像的结论。我很确定它可以。另外,我知道这不是一个完整的“解决方案”,很抱歉,没关系。如果我让它工作,我会给你检查和解决复选标记,并更新我的问题与解决方案。谢谢我认为这是正确的,因为这是我能说的最好的方法。问题在于OpenJDK,它不再支持JAI,但我发现的所有其他库都依赖ImageIO。@pstanton如果仔细查看您发布的源代码,您会发现如果从多个线程使用该方法,则不会阻塞。它抛出一个
非法状态异常
。PS:我认为你在帮助OP找到解决办法方面的努力值得表扬,别误会我的意思。只是我认为结论是错误的,并试图避免混淆。:-)那证明不了什么。您所证明的是,您可以将请求排队发送到解码器。你还没有证明他们是
Started reading image 5 (now decoding 2 images simultaneous)...
Started reading image 0 (now decoding 16 images simultaneous)...
Started reading image 14 (now decoding 15 images simultaneous)...
Started reading image 4 (now decoding 14 images simultaneous)...
Started reading image 13 (now decoding 1 images simultaneous)...
Started reading image 11 (now decoding 13 images simultaneous)...
Started reading image 2 (now decoding 12 images simultaneous)...
Started reading image 15 (now decoding 4 images simultaneous)...
Started reading image 8 (now decoding 11 images simultaneous)...
Started reading image 7 (now decoding 10 images simultaneous)...
Started reading image 9 (now decoding 9 images simultaneous)...
Started reading image 6 (now decoding 8 images simultaneous)...
Started reading image 10 (now decoding 7 images simultaneous)...
Started reading image 1 (now decoding 6 images simultaneous)...
Started reading image 3 (now decoding 5 images simultaneous)...
Started reading image 12 (now decoding 3 images simultaneous)...
Progress on image 11 (now decoding 16 images simultaneous)...
Progress on image 15 (now decoding 16 images simultaneous)...
Progress on image 13 (now decoding 16 images simultaneous)...
Progress on image 13 (now decoding 16 images simultaneous)...
Progress on image 9 (now decoding 16 images simultaneous)...
Progress on image 9 (now decoding 16 images simultaneous)...
Progress on image 1 (now decoding 16 images simultaneous)...
Progress on image 3 (now decoding 16 images simultaneous)...
Progress on image 1 (now decoding 16 images simultaneous)...
Progress on image 3 (now decoding 16 images simultaneous)...
Progress on image 1 (now decoding 16 images simultaneous)...
Progress on image 13 (now decoding 16 images simultaneous)...
Progress on image 5 (now decoding 16 images simultaneous)...
Progress on image 9 (now decoding 16 images simultaneous)...
Progress on image 3 (now decoding 16 images simultaneous)...
Done reading image 3 (still decoding 15 other images).
Started reading image 16 (now decoding 15 images simultaneous)...
Progress on image 11 (now decoding 15 images simultaneous)...
Done reading image 13 (still decoding 14 other images).
Started reading image 17 (now decoding 15 images simultaneous)...
Progress on image 5 (now decoding 15 images simultaneous)...
Progress on image 4 (now decoding 15 images simultaneous)...
Progress on image 11 (now decoding 15 images simultaneous)...
Done reading image 9 (still decoding 14 other images).
Progress on image 5 (now decoding 15 images simultaneous)...
Progress on image 17 (now decoding 15 images simultaneous)...
Done reading image 11 (still decoding 14 other images).
Started reading image 19 (now decoding 15 images simultaneous)...
Progress on image 17 (now decoding 15 images simultaneous)...
Done reading image 5 (still decoding 14 other images).
Started reading image 18 (now decoding 15 images simultaneous)...
Progress on image 15 (now decoding 15 images simultaneous)...
Done reading image 1 (still decoding 14 other images).
Started reading image 21 (now decoding 15 images simultaneous)...
Progress on image 15 (now decoding 15 images simultaneous)...
Progress on image 21 (now decoding 15 images simultaneous)...
Done reading image 15 (still decoding 14 other images).
Progress on image 6 (now decoding 14 images simultaneous)...
Progress on image 21 (now decoding 14 images simultaneous)...
Progress on image 7 (now decoding 14 images simultaneous)...
Progress on image 21 (now decoding 14 images simultaneous)...
Progress on image 7 (now decoding 14 images simultaneous)...
Progress on image 19 (now decoding 14 images simultaneous)...
Progress on image 19 (now decoding 14 images simultaneous)...
Progress on image 7 (now decoding 14 images simultaneous)...
Progress on image 19 (now decoding 14 images simultaneous)...
Done reading image 7 (still decoding 13 other images).
Started reading image 23 (now decoding 14 images simultaneous)...
Progress on image 10 (now decoding 14 images simultaneous)...
Progress on image 23 (now decoding 14 images simultaneous)...
Progress on image 14 (now decoding 14 images simultaneous)...
Started reading image 22 (now decoding 15 images simultaneous)...
Progress on image 0 (now decoding 15 images simultaneous)...
Done reading image 21 (still decoding 14 other images).
Started reading image 24 (now decoding 15 images simultaneous)...
Started reading image 20 (now decoding 16 images simultaneous)...
Progress on image 2 (now decoding 16 images simultaneous)...
Progress on image 8 (now decoding 16 images simultaneous)...
Progress on image 17 (now decoding 15 images simultaneous)...
Done reading image 17 (still decoding 14 other images).
Started reading image 25 (now decoding 15 images simultaneous)...
Progress on image 23 (now decoding 15 images simultaneous)...
Done reading image 19 (still decoding 15 other images).
Started reading image 26 (now decoding 16 images simultaneous)...
Progress on image 23 (now decoding 16 images simultaneous)...
Done reading image 23 (still decoding 15 other images).
Started reading image 27 (now decoding 16 images simultaneous)...
Progress on image 4 (now decoding 16 images simultaneous)...
Progress on image 27 (now decoding 16 images simultaneous)...
Progress on image 27 (now decoding 16 images simultaneous)...
Progress on image 6 (now decoding 16 images simultaneous)...
Progress on image 12 (now decoding 16 images simultaneous)...
Progress on image 20 (now decoding 16 images simultaneous)...
Progress on image 0 (now decoding 16 images simultaneous)...
Progress on image 25 (now decoding 16 images simultaneous)...
Progress on image 25 (now decoding 16 images simultaneous)...
Progress on image 25 (now decoding 16 images simultaneous)...
Progress on image 14 (now decoding 16 images simultaneous)...
Progress on image 10 (now decoding 16 images simultaneous)...
Progress on image 8 (now decoding 16 images simultaneous)...
Progress on image 18 (now decoding 16 images simultaneous)...
Done reading image 25 (still decoding 15 other images).
Progress on image 75 (now decoding 12 images simultaneous)...
Started reading image 73 (now decoding 13 images simultaneous)...
Progress on image 75 (now decoding 13 images simultaneous)...
Progress on image 73 (now decoding 13 images simultaneous)...
Progress on image 75 (now decoding 13 images simultaneous)...
Started reading image 74 (now decoding 14 images simultaneous)...
Progress on image 66 (now decoding 14 images simultaneous)...
Progress on image 64 (now decoding 14 images simultaneous)...
Progress on image 73 (now decoding 14 images simultaneous)...
Progress on image 60 (now decoding 14 images simultaneous)...
Progress on image 74 (now decoding 14 images simultaneous)...
Progress on image 58 (now decoding 14 images simultaneous)...
Done reading image 75 (still decoding 13 other images).
Progress on image 73 (now decoding 13 images simultaneous)...
Started reading image 77 (now decoding 14 images simultaneous)...
Done reading image 73 (still decoding 13 other images).
Progress on image 77 (now decoding 13 images simultaneous)...
Started reading image 78 (now decoding 14 images simultaneous)...
Progress on image 60 (now decoding 14 images simultaneous)...
Done reading image 48 (still decoding 13 other images).
Progress on image 77 (now decoding 13 images simultaneous)...
Started reading image 79 (now decoding 14 images simultaneous)...
Started reading image 70 (now decoding 15 images simultaneous)...
Progress on image 52 (now decoding 15 images simultaneous)...
Progress on image 71 (now decoding 15 images simultaneous)...
Started reading image 72 (now decoding 16 images simultaneous)...
Progress on image 71 (now decoding 16 images simultaneous)...
Progress on image 54 (now decoding 16 images simultaneous)...
Progress on image 68 (now decoding 16 images simultaneous)...
Progress on image 64 (now decoding 16 images simultaneous)...
Progress on image 66 (now decoding 16 images simultaneous)...
Progress on image 62 (now decoding 16 images simultaneous)...
Progress on image 79 (now decoding 16 images simultaneous)...
Progress on image 79 (now decoding 16 images simultaneous)...
Progress on image 79 (now decoding 16 images simultaneous)...
Progress on image 77 (now decoding 16 images simultaneous)...
Progress on image 68 (now decoding 16 images simultaneous)...
Done reading image 79 (still decoding 15 other images).
Done reading image 77 (still decoding 14 other images).
Started reading image 81 (now decoding 15 images simultaneous)...
Progress on image 74 (now decoding 15 images simultaneous)...
Progress on image 81 (now decoding 15 images simultaneous)...
Progress on image 81 (now decoding 15 images simultaneous)...
Progress on image 78 (now decoding 15 images simultaneous)...
Done reading image 60 (still decoding 14 other images).
Started reading image 82 (now decoding 15 images simultaneous)...
Started reading image 80 (now decoding 16 images simultaneous)...
Progress on image 76 (now decoding 14 images simultaneous)...
Progress on image 66 (now decoding 14 images simultaneous)...
Progress on image 70 (now decoding 14 images simultaneous)...
Done reading image 52 (still decoding 14 other images).
Done reading image 71 (still decoding 15 other images).
Progress on image 81 (now decoding 16 images simultaneous)...
Started reading image 84 (now decoding 15 images simultaneous)...
Started reading image 83 (now decoding 16 images simultaneous)...
Progress on image 58 (now decoding 16 images simultaneous)...
Progress on image 83 (now decoding 16 images simultaneous)...
Progress on image 83 (now decoding 16 images simultaneous)...
Progress on image 83 (now decoding 16 images simultaneous)...
Done reading image 81 (still decoding 15 other images).
Started reading image 85 (now decoding 16 images simultaneous)...
Progress on image 85 (now decoding 16 images simultaneous)...
Progress on image 74 (now decoding 16 images simultaneous)...
Done reading image 66 (still decoding 15 other images).
Started reading image 86 (now decoding 16 images simultaneous)...
Progress on image 64 (now decoding 16 images simultaneous)...
Progress on image 70 (now decoding 16 images simultaneous)...
Progress on image 78 (now decoding 16 images simultaneous)...
Progress on image 54 (now decoding 16 images simultaneous)...
Done reading image 58 (still decoding 15 other images).
Started reading image 87 (now decoding 16 images simultaneous)...
Progress on image 87 (now decoding 16 images simultaneous)...
Progress on image 84 (now decoding 16 images simultaneous)...
Progress on image 87 (now decoding 16 images simultaneous)...
Done reading image 64 (still decoding 15 other images).
Started reading image 88 (now decoding 16 images simultaneous)...
Progress on image 76 (now decoding 16 images simultaneous)...
Done reading image 83 (still decoding 15 other images).
Progress on image 62 (now decoding 15 images simultaneous)...
Progress on image 70 (now decoding 16 images simultaneous)...
Progress on image 85 (now decoding 16 images simultaneous)...
Started reading image 89 (now decoding 16 images simultaneous)...
Progress on image 72 (now decoding 16 images simultaneous)...
Progress on image 85 (now decoding 16 images simultaneous)...
Progress on image 89 (now decoding 16 images simultaneous)...
Done reading image 85 (still decoding 15 other images).
Progress on image 89 (now decoding 15 images simultaneous)...
Progress on image 82 (now decoding 15 images simultaneous)...
Progress on image 80 (now decoding 15 images simultaneous)...
Done reading image 74 (still decoding 14 other images).
Started reading image 91 (now decoding 15 images simultaneous)...
Started reading image 90 (now decoding 16 images simultaneous)...
Done reading image 62 (still decoding 15 other images).
Progress on image 87 (now decoding 15 images simultaneous)...
Progress on image 68 (now decoding 15 images simultaneous)...
Done reading image 87 (still decoding 14 other images).
Progress on image 91 (now decoding 14 images simultaneous)...
Started reading image 93 (now decoding 15 images simultaneous)...
Progress on image 93 (now decoding 15 images simultaneous)...
Progress on image 91 (now decoding 15 images simultaneous)...
Progress on image 91 (now decoding 15 images simultaneous)...
Progress on image 80 (now decoding 15 images simultaneous)...
Started reading image 92 (now decoding 16 images simultaneous)...
Done reading image 91 (still decoding 15 other images).
Started reading image 94 (now decoding 16 images simultaneous)...
Progress on image 93 (now decoding 16 images simultaneous)...
Progress on image 72 (now decoding 16 images simultaneous)...
Progress on image 93 (now decoding 16 images simultaneous)...
Done reading image 93 (still decoding 15 other images).
Started reading image 95 (now decoding 16 images simultaneous)...
Progress on image 95 (now decoding 16 images simultaneous)...
Progress on image 95 (now decoding 16 images simultaneous)...
Progress on image 76 (now decoding 16 images simultaneous)...
Progress on image 95 (now decoding 16 images simultaneous)...
Progress on image 72 (now decoding 16 images simultaneous)...
Done reading image 95 (still decoding 15 other images).
Started reading image 96 (now decoding 16 images simultaneous)...
Progress on image 94 (now decoding 16 images simultaneous)...
Progress on image 89 (now decoding 15 images simultaneous)...
Done reading image 89 (still decoding 14 other images).
Done reading image 54 (still decoding 15 other images).
Started reading image 97 (now decoding 14 images simultaneous)...
Started reading image 98 (now decoding 15 images simultaneous)...
Done reading image 70 (still decoding 13 other images).
Started reading image 99 (now decoding 16 images simultaneous)...
Progress on image 82 (now decoding 16 images simultaneous)...
Progress on image 99 (now decoding 16 images simultaneous)...
Progress on image 99 (now decoding 16 images simultaneous)...
Progress on image 97 (now decoding 16 images simultaneous)...
Progress on image 97 (now decoding 16 images simultaneous)...
Progress on image 97 (now decoding 16 images simultaneous)...
Done reading image 68 (still decoding 15 other images).
Done reading image 97 (still decoding 14 other images).
Progress on image 78 (now decoding 14 images simultaneous)...
Progress on image 99 (now decoding 14 images simultaneous)...
Done reading image 99 (still decoding 13 other images).
Progress on image 86 (now decoding 13 images simultaneous)...
Done reading image 72 (still decoding 12 other images).
Progress on image 82 (now decoding 12 images simultaneous)...
Progress on image 98 (now decoding 12 images simultaneous)...
Progress on image 84 (now decoding 12 images simultaneous)...
Progress on image 90 (now decoding 12 images simultaneous)...
Done reading image 76 (still decoding 11 other images).
Progress on image 92 (now decoding 11 images simultaneous)...
Progress on image 80 (now decoding 11 images simultaneous)...
Progress on image 94 (now decoding 11 images simultaneous)...
Progress on image 88 (now decoding 11 images simultaneous)...
Progress on image 84 (now decoding 11 images simultaneous)...
Progress on image 90 (now decoding 11 images simultaneous)...
Progress on image 92 (now decoding 11 images simultaneous)...
Progress on image 86 (now decoding 11 images simultaneous)...
Progress on image 94 (now decoding 10 images simultaneous)...
Done reading image 84 (still decoding 9 other images).
Progress on image 92 (now decoding 9 images simultaneous)...
Done reading image 78 (still decoding 10 other images).
Progress on image 88 (now decoding 9 images simultaneous)...
Progress on image 90 (now decoding 9 images simultaneous)...
Done reading image 80 (still decoding 8 other images).
Done reading image 82 (still decoding 7 other images).
Progress on image 86 (now decoding 7 images simultaneous)...
Progress on image 96 (now decoding 7 images simultaneous)...
Progress on image 88 (now decoding 7 images simultaneous)...
Done reading image 90 (still decoding 6 other images).
Done reading image 92 (still decoding 5 other images).
Progress on image 98 (now decoding 5 images simultaneous)...
Done reading image 94 (still decoding 4 other images).
Done reading image 86 (still decoding 3 other images).
Progress on image 96 (now decoding 3 images simultaneous)...
Done reading image 88 (still decoding 2 other images).
Progress on image 98 (now decoding 2 images simultaneous)...
Progress on image 96 (now decoding 2 images simultaneous)...
Done reading image 98 (still decoding 1 other images).
Done reading image 96.