Безопасный обновить отдельные регионы BufferedImage в отдельных потоках?

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

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

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

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

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

5
задан finnw 21 May 2010 в 12:56
поделиться

4 ответа

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

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

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

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

4
ответ дан 14 December 2019 в 08:44
поделиться

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

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

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

Решите эту проблему:

        W1       W2      W3
Img1 |-------|-------|-------|
        W1       W2      W3
Img2 |-------|-------|-------|
Кому:
        W1       W1      W1
Img1 |-------|-------|-------|
        W2       W2      W2
Img2 |-------|-------|-------|
    
1
ответ дан 14 December 2019 в 08:44
поделиться

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

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

2
ответ дан 14 December 2019 в 08:44
поделиться

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

Изучите источник BufferedImage, DataBuffer, Raster и т. Д. Это единственный способ.

0
ответ дан 14 December 2019 в 08:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: