У меня есть набор BufferedImage
экземпляры, одно основное изображение и некоторые подызображения создаются путем вызова getSubImage
на основном изображении. Подызображения не накладываются. Я также делаю модификации к подызображению, и я хочу разделить это на несколько потоков, один на подызображение.
От моего понимания как BufferedImage
, Raster
и DataBuffer
работа, это должно быть безопасно потому что:
BufferedImage
(и его соответствующее WritableRaster
и SampleModel
) получен доступ только от одного потока.ColorModel
неизменноDataBuffer
не имеет никаких полей, которые могут быть изменены (единственная вещь, которая может измениться, элементы вспомогательного массива.)Однако я ничего не могу найти в документации, в которой говорится, что определенно безопасно сделать это. Я могу предположить, что это безопасно? Я знаю, что возможно работать над копиями ребенка Raster
s, но я предпочел бы избегать этого из-за ограничений памяти.
Иначе действительно ли возможно сделать операцию ориентированной на многопотоковое исполнение, не копируя области родительского изображения?
Рассматривали ли вы возможность использования JAI для управления "подизображениями" в виде плиток? Это кажется лучшим использованием ресурсов, если вам не нужно держать экземпляр BufferedImage исходного изображения, а также все его подэкземпляры BufferedImage. Информацию о JAI можно найти здесь: JAI README
Существует класс TiledImage, который реализует интерфейс RenderedImage (что дает ему общего предка с BufferedImage). Согласно документации JAI:
Использование тайлинга также облегчает использование нескольких потоков для вычислений. Ранее выделенные плитки могут также использоваться повторно для экономии памяти.
Использование одной из этих реализаций RenderedImage часто предпочтительнее, чем BufferedImage, поскольку BufferedImage сохраняет в памяти снимок изображения для всего изображения. JAI использует цепочку рендеринга и может перерабатывать плитки по мере необходимости, чтобы соответствовать ограничениям памяти.
Я не нашел никаких явных доказательств безопасности потоков BufferedImage
, но вы, вероятно, можете решить вашу проблему следующим образом:
Вместо одновременной обработки фрагментов изображений с помощью разные рабочие, старайтесь обрабатывать много изображений так, чтобы каждый рабочий использовал разные фрагменты одного и того же изображения. Один и тот же воркер будет обрабатывать фрагменты одного и того же изображения, но последовательно.
Ваши рабочие будут заняты, пока не останется меньше изображений, чем осталось рабочих.
Решите эту проблему:
W1 W2 W3 Img1 |-------|-------|-------| W1 W2 W3 Img2 |-------|-------|-------|Кому:
W1 W1 W1 Img1 |-------|-------|-------| W2 W2 W2 Img2 |-------|-------|-------|
Это хороший анализ, и мне он кажется правильным. Нет общих данных, поэтому одновременный доступ должен быть нормальным. Однако вам нужна какая-то гарантия, а не обоснованное предположение, что это должно сработать. Даже если вы найдете утверждение, что «BufferedImage предназначен для одновременного использования» - нет никакой гарантии, что это так на практике.
Чтобы быть максимально уверенным, вы можете написать параллельный модульный тест, используя ConTest . Жгуты параллельного тестирования инструментируют ваш код и внедряют искусственно вызванные переключатели контекста, чтобы выявить ошибки параллелизма. Это позволит протестировать код BufferedImage и ваш собственный код, поэтому вы можете быть уверены, что он безопасен для потоков.
Если ни один из этих ответов не удовлетворяет (достаточно), вы можете сделать что-то, что окончательно решит вопрос по высокой (?) Цене.
Изучите источник BufferedImage, DataBuffer, Raster и т. Д. Это единственный способ.