I have a collection of BufferedImage
instances, one main image and some subimages created by calling getSubImage
on the main image. The subimages do not overlap. I am also making modifications to the subimage and I want to split this into multiple threads, one per subimage.
From my understanding of how BufferedImage
, Raster
and DataBuffer
work, this should be safe because:
BufferedImage
(and its respective WritableRaster
and SampleModel
) is accessed from only one thread.ColorModel
is immutableDataBuffer
has no fields that can be modified (the only thing that can change is elements of the backing array.)However I cannot find anything in the documentation that says that it is definitely safe to do this. Can I assume it is safe? I know that it is possible to work on copies of the child Raster
s but I would prefer to avoid this because of memory constraints.
Otherwise, is it possible to make the operation thread-safe without copying regions of the parent image?
Have you looked into using JAI to manage your 'subimages' as tiles? It seems like a better use of resources if you don't have to hang onto the original image BufferedImage instance as well as all its subImage BufferedImage instance. Information about JAI can be found here: JAI README
There is a class, TiledImage, which implements the RenderedImage interface (giving it a common ancestor with BufferedImage). According to the JAI documentation:
The use of tiling also facilitates the use of multiple threads for computation. Previously allocated tiles may also be re-used to save memory.
Using one of these implementations of RenderedImage is often preferrable to a BufferedImage anyway, since the BufferedImage maintains an image snapshot in memory for the entire image. JAI uses a rendering chain and can recycle tiles as needed to fit memory constraints.
That's a good analysis, and it sounds correct to me. There is no shared data, so concurrent access should be fine. However, you need some kind of guarantee to be sure, more than a educated guess that it should work. Even if you find a statement saying "BufferedImage is designed to be used concurrently" - there is no guarantee that this is the case in practice.
To be as sure as you can be, you can write a concurrent unit test using ConTest. The concurrent test harness instruments your code and injects artificially induced context switches to expose concurrency bugs. This will test the BufferedImage code and your own code, so you can have a high degree of confidence that it is thread safe.
I haven't found any clear evidence of thread safety of BufferedImage
, but you probably can solve your problem the next way:
Instead of simultaneous processing of subimages by different workers, try to process many images in the way that every worker consumes different subimages of the same image. The same worker will be processing subimages of the same image, but sequentially.
Your workers would be busy until there are less images than workers remained.
Revert this problem:
W1 W2 W3 Img1 |-------|-------|-------| W1 W2 W3 Img2 |-------|-------|-------|To:
W1 W1 W1 Img1 |-------|-------|-------| W2 W2 W2 Img2 |-------|-------|-------|
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With