Безопасно ли обновлять отдельные области BufferedImage в отдельных потоках? - PullRequest
5 голосов
/ 18 мая 2010

У меня есть коллекция BufferedImage экземпляров, одно основное изображение и несколько подизображений, созданных путем вызова getSubImage на основном изображении. Подизображения не перекрываются. Я также делаю изменения в подизображении и хочу разделить его на несколько потоков, по одному на каждый подизображение.

Из моего понимания того, как BufferedImage, Raster и DataBuffer работают, это должно быть безопасно, потому что:

  • Каждый экземпляр BufferedImage (и соответствующие ему WritableRaster и SampleModel) доступен только из одного потока.
  • Общая ColorModel неизменна
  • DataBuffer не имеет полей, которые можно изменить (единственное, что можно изменить, - это элементы массива поддержки).
  • Модификация непересекающихся сегментов массива в отдельных потоках безопасна.

Однако я не могу найти ничего в документации, которая говорит, что это безопасно. Могу ли я предположить, что это безопасно? Я знаю, что можно работать с дочерними копиями Raster s, но я бы предпочел избежать этого из-за ограничений памяти.

В противном случае возможно ли сделать операцию поточно-ориентированной, не копируя области родительского изображения?

Ответы [ 4 ]

4 голосов
/ 21 мая 2010

Вы рассматривали возможность использования JAI для управления вашими «изображениями» в качестве плиток? Похоже, лучше использовать ресурсы, если вам не нужно висеть на исходном образе BufferedImage, а также на всем его экземпляре SubImage BufferedImage. Информацию о JAI можно найти здесь: JAI README

Существует класс TiledImage, который реализует интерфейс RenderedImage (предоставляя ему общего предка с BufferedImage). Согласно документации JAI:

Использование черепицы также облегчает использование нескольких потоков для вычисление. Ранее выделенный плитки также могут быть повторно использованы для сохранения память.

Использование одной из этих реализаций RenderedImage часто в любом случае предпочтительнее BufferedImage, поскольку BufferedImage поддерживает снимок изображения в памяти для всего изображения. JAI использует цепочку рендеринга и может перерабатывать плитки по мере необходимости, чтобы соответствовать ограничениям памяти.

2 голосов
/ 24 мая 2010

Это хороший анализ, и для меня это звучит правильно. Нет общих данных, поэтому одновременный доступ должен быть в порядке. Однако, чтобы быть уверенным, вам нужна какая-то гарантия, а не догадка о том, что она должна работать. Даже если вы найдете утверждение о том, что «BufferedImage разработан для одновременного использования» - на практике это не гарантируется.

Для большей уверенности вы можете написать параллельный модульный тест, используя ConTest . Параллельное тестирование использует ваш код и внедряет искусственно вызванные переключатели контекста для выявления ошибок параллелизма. Это проверит код BufferedImage и ваш собственный код, так что вы сможете с высокой степенью уверенности убедиться, что он является поточно-ориентированным.

1 голос
/ 21 мая 2010

Я не нашел четких доказательств безопасности потоков BufferedImage, но вы, вероятно, можете решить свою проблему следующим образом:

Вместо одновременной обработки подизображений разными работниками, попробуйте обработать много изображений так, чтобы каждый работник потреблял разные подизображения одного и того же изображения. Один и тот же работник будет обрабатывать изображения одного и того же изображения, но последовательно.

Ваши работники будут заняты, пока не останется меньше изображений, чем осталось работников.

Вернуть эту проблему:

        W1       W2      W3
Img1 |-------|-------|-------|
        W1       W2      W3
Img2 |-------|-------|-------|
To:
        W1       W1      W1
Img1 |-------|-------|-------|
        W2       W2      W2
Img2 |-------|-------|-------|
    
0 голосов
/ 24 мая 2010

Если ни один из этих ответов не удовлетворит (достаточно), вы могли бы сделать что-то, что окончательно решит вопрос по высокой (?) Цене.

Проверьте источник для BufferedImage, DataBuffer, Raster и т. Д. Это единственный способ.

...