Является ли метод Swing repaint () все еще безопасным для использования вне EDT в Java 7+?
Я знаю, что раньше считалось безопасным звонить repaint()
и несколько других выбранных методов из любого потока даже с моделью резьбы Swing, однако мне недавно сказали в комментарии, что это не так.
Google нашел много старых обсуждений, говорящих, что это безопасно, но ничего в последнее время. Все официальные ссылки, которые раньше говорили, что это безопасно, похоже, исчезли, и я нашел несколько человек на разных форумах, обсуждающих, как это больше не безопасно.
I не могу найти ничего официального, чтобы подтвердить, является ли это или нет, и я действительно хотел бы увидеть что - то, объясняющее логику изменения, если оно было изменено. Учитывая, насколько сильно это рискует нарушить существующие приложения, кажется очень странной функцией удаления.
действительно, я ищу ссылку на официальную ссылку (например, Javadoc, Oracle tutorial или ссылку исходного кода), говоря, являются ли эти методы или все еще не безопасны для вызова из любого нитка.
Для справки этот вопрос здесь:
Безопасный в использовании компонент.перекрасить () снаружи EDT?
дает цитату из теперь исчезнувшей страницы Солнца, говоря:
следующие методы JComponent безопасны для вызова из любого потока: repaint(), revalidate () и invalidate(). Методы repaint() и revalidate() запрашивают очередь для потока диспетчеризации событий для вызова paint() и validate () соответственно.
Это соответствует моему пониманию, но я не могу найти эту страницу или любую подобную страницу сейчас, и я видел неподтвержденные слухи от нескольких людей, говорящих, что это больше не безопасно. Но с другой стороны, я не могу найти ничего определенного, говорящего о том, что эта функция изменилась.
изменить Примечания
что может помочь решить этот вопрос, это официальное заявление Oracle об изменениях в обработке потоков Swing. Я нашел "изменения в Java 7 " Страница, но это не упоминало об этом вообще, ни одна из этих страниц не упоминает threading или EDT в любом случае:
http://docs.oracle.com/javase/7/docs/technotes/guides/swing/enhancements-7.html
http://docs.oracle.com/javase/7/docs/technotes/guides/awt/enhancements-7.html
3 ответов
это официальная ссылка:
политика резьбы свинга
вообще качание не потокобезопасно. Все компоненты Swing и связанные классы, если не задокументировано иное, должны быть доступны в потоке диспетчеризации событий.
и repaint
метод не "ином документе".
чтобы вдвойне заверить вас, что вам не нужно смотреть дальше, чем Javadoc отдельного метода для окончательный ответ см., например, как была задокументирована безопасность потока метода в Java 6 Javadoc.
обновление
по-видимому, требуется больше разъяснений относительно различия между нормативными спецификациями, описательными техническими статьями и деталями любой конкретной реализации. В Javadoc говорится следующее:нет никакой гарантии, что repaint
является потокобезопасным методом. Кстати, часто обсуждаемое решение в Java 7 для удалить" потокобезопасное " обозначение из большинства API Swing было просто: изменение в контракт, а не реализации.
конкретная реализация repaint
в OpenJDK 7 кажется потокобезопасным, факт, который не имеет ничего общего с гарантиями, данными спецификацией. Код, который зависит от безопасности потока repaint
или другие методы сломанные и не гарантируется правильное поведение во всех реализациях Java.
как говорится в живопись в AWT и Swing: обработка краски,
JComponent.repaint()
регистрирует асинхронный запрос на перерисовку компонентаRepaintManager
, который используетinvokeLater()
в очередьRunnable
для последующей обработки запроса в потоке диспетчеризации событий.
это необходимое, но недостаточное условие для установления происходит-перед связь между последовательными вызовами repaint()
. На практике вам все равно нужно синхронизировать доступ к любым данным, которые разделяются между потоками. Без этого невозможно обеспечить видимость любых изменений, которые могут повлиять на последующий вызов repaint()
.
Я бы сказал, что это еще потокобезопасным. Метод repaint () не изменяет свойство любого компонента Swing.
метод repaint () вызывает RepaintManager. Затем RepaintManager (потенциально) объединит несколько запросов рисования в один запрос рисования. Затем он добавит запрос paint в EDT для обработки.