可以安全地在单独的线程中更新BufferedImage的单独区域吗?

时间:2010-05-18 12:47:31

标签: java multithreading thread-safety bufferedimage

我有一组BufferedImage个实例,一个主图像和一些通过在主图像上调用getSubImage创建的子图像。子图像不重叠。我也在修改子图像,我想把它分成多个线程,每个子图像一个。

根据我对BufferedImageRasterDataBuffer工作原理的理解,这应该是安全的,因为:

  • BufferedImage(及其各自的WritableRasterSampleModel)的每个实例仅从一个主题访问。
  • 共享ColorModel是不可变的
  • DataBuffer没有可以修改的字段(唯一可以改变的是支持数组的元素。)
  • 在单独的线程中修改数组的不相交段是安全的。

但是我在文档中找不到任何说明这样做绝对安全的内容。我可以认为它是安全的吗?我知道可以处理子Raster的副本,但由于内存限制,我宁愿避免这种情况。

否则,是否可以在不复制父图像区域的情况下使操作成为线程安全的?

4 个答案:

答案 0 :(得分:4)

您是否考虑过使用JAI将'子图像'作为图块进行管理?如果你不必挂起原始图像BufferedImage实例以及它的所有subImage BufferedImage实例,它似乎更好地利用了资源。有关JAI的信息可以在这里找到: JAI README

有一个类TiledImage,它实现了RenderedImage接口(给它一个带有BufferedImage的共同祖先)。根据JAI文件:

  

使用平铺也有利于   使用多个线程   计算。以前分配过   瓷砖也可以重新用于保存   存储器中。

使用RenderedImage的这些实现之一通常更喜欢BufferedImage,因为BufferedImage在内存中为整个图像维护一个图像快照。 JAI使用渲染链,可以根据需要回收切片以适应内存约束。

答案 1 :(得分:2)

这是一个很好的分析,对我来说听起来是对的。没有共享数据,因此并发访问应该没问题。但是,你需要某种保证才能确定,而不是有根据的猜测它应该有效。即使您发现声明“BufferedImage旨在同时使用” - 也无法保证在实践中就是这种情况。

为了尽可能确定,您可以使用ConTest编写并发单元测试。并发测试工具为您的代码提供工具,并注入人工引发的上下文切换以暴露并发错误。这将测试BufferedImage代码和您自己的代码,因此您可以高度确信它是线程安全的。

答案 2 :(得分:1)

我没有找到BufferedImage的线程安全的任何明确证据,但您可能可以通过下一个方式解决您的问题:

不是由不同的工作人员同时处理子图像,而是尝试以每个工作者消耗同一图像的不同子图像的方式处理许多图像。同一个工作人员将处理同一图像的子图像,但是按顺序处理。

你的工人会很忙,直到图像少于工人。

还原此问题:     

        W1       W2      W3
Img1 |-------|-------|-------|
        W1       W2      W3
Img2 |-------|-------|-------|
到:

        W1       W1      W1
Img1 |-------|-------|-------|
        W2       W2      W2
Img2 |-------|-------|-------|
    

答案 3 :(得分:0)

如果这些答案都不满足(足够),你可以做一些能够以沉重的(?)价格最终解决问题的事情。

Examine the source for BufferedImage, DataBuffer, Raster, etc.这是唯一的方式。