2014-10-10 2 views
4

Я вижу в спецификации javax.imageio, что безопасность потока не является целью, несмотря на то, что я видел несколько примеров, используя ImageIO.read() и ImageIO.write() для загрузки/дезинфекции изображений в веб-среде.ImageIO thread-safety

Итак, мой вопрос, несмотря на то, что говорит спецификация, является ImageIO потокобезопасным?

ответ

0

Я проверил класс и не существует состояния и почти всех классов, которые не имеют гражданства. (Я не проверял все функции. Лучше проверять функции перед использованием)

Скорее всего, это безопасный поток.

+0

Спасибо за ваш ответ, @ user3087839, но "скорее всего" не достаточно для меня ... – Alex

4

TLDR; Да, статические методы ImageIO.read(...) и write(...) являются потокобезопасными.


Часть спецификации, которая говорит "thread safety is not a goal" потребности следует рассматривать в контексте. То, что на самом деле говорит спецификация, заключается в том, что отдельные версии ImageReader, ImageWriter или ImageInputStream/ImageOutputStream не должны заботиться о безопасности потоков (и, как результат, клиентский код никогда не должен считать, что они потокобезопасны). Пока вы живете по этому правилу, вы в безопасности. Однако обратите внимание, что в той же части спецификации также указано, что:

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

Эта часть спецификации не обсуждать статические методы ImageIO особенно, но выше цитаты следует, что Теза метода поточно как ImageIO.read(...) и write(...) создает новые экземпляры ImageInputStream/ImageOutputStream и ImageReader/ImageWriter для каждого призывание. Таким образом, это действительно не «несмотря на то, что спецификация говорит«.

Класс ImageIO состоит из нескольких других статических методов, которые могут быть безопасными в использовании, а сам класс является (главным образом *) безстоящим. Если это не работает таким образом, это не будет действительно много пользы ...

  • IIORegistry экземпляр ImageIO заполняется во время создания класса, и повторно инициализируется каждый раз, когда метод scanForPlugins() вызывается. У вас могут возникнуть проблемы (например, плагины могут быть неправильно зарегистрированы), если два потока вызывают его в одно и то же время, но в качестве контроля кода клиента, где/когда это происходит, вы можете легко избежать этого. Существует также группа потоков CacheInfo, но ее использование, по-видимому, правильно синхронизировано.

Отказ от ответственности, я не писала спецификации, но это моя интерпретация (и я использовал ImageIO в бесчисленных, многопоточных приложениях, а также написал дюжину ImageReader и ImageWriter плагины сам) ,

+0

для моего понимания ты что использование конкретного «ImageReader» небезопасно, но использование 'ImageIO.read()' безопасно ? – Alex

+0

Полностью безопасно использовать ImageReader, даже несколько экземпляров одновременно. Они просто не являются потокобезопасными, по смыслу вы не можете делиться * единственным экземпляром * между * несколькими потоками * (то есть, у ImageReader есть состояние). – haraldK

+0

Понял, но вы можете использовать один метод 'ImageIO' одновременно в нескольких потоках? – Alex

4

ImageIO не является потокобезопасным (или, по крайней мере, одним из его плагинов нет), по крайней мере в одной из моих сред. Я в процессе отладки проблемы, когда файлы png и jpg загружаются неправильно (иногда сплошные серые, иногда перевернутые цвета, иногда случайные цвета и т. Д.), Когда ImageIO.read() вызывается из нескольких потоков. я иногда получить ConcurrentModificationExceptions как:

java.util.ConcurrentModificationException 
at java.util.Vector$Itr.checkForComodification(Vector.java:1184) 
at java.util.Vector$Itr.next(Vector.java:1137) 
at sun.java2d.cmm.ProfileDeferralMgr.activateProfiles(ProfileDeferralMgr.java:93) 
at java.awt.color.ICC_Profile.getInstance(ICC_Profile.java:777) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.setImageData(JPEGImageReader.java:657) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readNativeHeader(JPEGImageReader.java:609) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.checkTablesOnly(JPEGImageReader.java:347) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.gotoImage(JPEGImageReader.java:481) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readHeader(JPEGImageReader.java:602) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1059) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:1039) 
at javax.imageio.ImageIO.read(ImageIO.java:1448) 
at javax.imageio.ImageIO.read(ImageIO.java:1308) 
at com.foo.bar.MyTestLoadThread.loadImage(MyTestLoadThread.java:241) 
... 
at java.lang.Thread.run(Thread.java:745) 

Я не в состоянии воспроизвести такое поведение во всех средах, так что это может быть JVM специфичны. Но вот подробности env. где я вижу, что не в состоянии:

  • ОС: Ubuntu 14,04
  • Java -версия:
    Java версия "1.8.0_33"
    Java (TM) SE Runtime Environment (сборка 1.8.0_33-B05)
    Java HotSpot (TM) Client VM (сборка 25.33-B05, смешанный режим)
+0

ImageIO.write также не является потокобезопасным. Вызов из нескольких потоков приводит к артефактам: https://i.imgur.com/tiOZjQ7.png –

+0

Этот ответ относится к известной ошибке OpenJDK, [JDK-6986863] (https://bugs.openjdk.java.net/ browse/JDK-6986863), к сожалению, пока не исправлены (во время этой публикации). Это проблема (threading?), Которая существует в подсистеме управления цветом Java2D, за исключением 'ImageIO'. – haraldK

Смежные вопросы