2

我正在编写一个程序,该程序涉及对许多图像的自定义搜索。当用户输入他们的搜索条件时,从缓存或服务器中检索相应的图像。我有一个 JTable,它显示指向相应图像的链接。当用户单击链接时,图像将显示在 JPanel 上。单击链接时,我可以从硬盘驱动器读取图像,但速度不如我想的那么快。加载它需要几秒钟。我曾尝试创建一个 BufferedImages 数组,但如果搜索返回许多结果,我会去 oom。我想知道单击链接时使图像显示得更快的最佳方法是什么。

这是我获取图像的方法...

Public void getFile(String fileName){
File file = new File("./cache/"+fileName);
    boolean exists = file.exists();

    BufferedImage returnImage =null;
    if(exists){
        try {

            returnImage = ImageIO.read(file);
            System.out.println("Found In Cache!");
        } catch (IOException|IndexOutOfBoundsException e) {
            try {
                if(fileName != null){
                returnImage = downloadImage(fileName);
                System.out.println("Found ON Server :(");
                }
            } catch (IOException |IndexOutOfBoundsException ex) {
                // TODO Auto-generated catch block
                ex.printStackTrace();
            }
        }
    }else{
        try {
            if(fileName != null){
            returnImage = downloadImage(fileName);
            System.out.println("Found ON Server :(");
            }
        } catch (IOException |IndexOutOfBoundsException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    return returnImage; 

}
}

这就是我把它们放在一个数组中的地方......

BufferedImage[] images = new BufferedImage[numOfSearchResults];

for(SearchResult r: results){
     images[i] = imageCache.getFile(r.imageName);
}

基本上,我只是想知道在不出现 oom 的情况下预加载图像的最佳方法是什么。提前致谢

4

4 回答 4

3

从磁盘加载图像需要几秒钟的时间听起来很不合理,除非图像真的非常大(10 兆像素或更多)。首先确定时间真正花在了哪里。

对于缓存,您可以保存对使用 java.lang.ref.SoftReference 加载的每个图像的引用 - 这允许在运行 OOM之前对图像进行垃圾收集。如果真的无法避免,我会使用多层缓存系统,第一层在内存中使用 SoftReferences,对于基于服务器的图像,使用额外的磁盘缓存。查找图像时,首先检查内存缓存,如果没有找到磁盘缓存,则检查磁盘缓存,如果仍未找到,则以通常的方式加载图像。

于 2012-07-25T16:24:13.280 回答
2

不要加载所有/太多图像,在当前索引之前加载一对图像,在当前索引之后加载一对图像。

将图像加载器实现为一个不同的线程,它不会阻塞主执行线程并在用户观看当前加载的图像时加载其他图像。

于 2012-07-25T16:16:01.030 回答
0

如果您不需要完整尺寸的图像,我会在加载时缩小它们以减少内存量。您必须记住,加载到内存中的图像不再被压缩。

如果您可以控制源图像,我会考虑生成缩略图以帮助它们更快地加载。我们使用 200x200 的缩略图,甚至超过基于 SMB 的共享,加载时间不到一秒

于 2012-07-25T16:25:47.980 回答
0

您可以打开所有图像的 InputStream 并关闭用户未单击的图像,然后使用您需要的图像。

这样,您不必缓冲所有图像,而是在用户单击时让它们“触手可及”。

但是正如@Robin 正确评论的那样,加载平均大小的图像确实不需要很长时间。

我不确定这是否会大大提高您的性能,但根据您的情况,它可以。

于 2012-07-25T16:22:24.100 回答