Является ли метод Swing repaint() все еще безопасным для использования вне EDT в Java 7+?

Я знаю, что раньше звонить считалось безопасным repaint() и несколько других выбранных методов из любого потока, даже с потоковой моделью Swing, однако мне недавно сказали в комментарии, что это не так.

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

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

На самом деле я ищу ссылку на официальную ссылку (например, Javadoc, oracle tutorial или ссылку на исходный код), в которой указано, являются ли эти методы безопасными для вызова из какого-либо потока.

Для справки этот вопрос здесь:

Безопасно ли использовать Component.repaint() вне EDT?

Дает цитату из недавно исчезнувшей страницы Sun, в которой говорится:

Следующие методы JComponent безопасны для вызова из любого потока: repaint(), revalidate() и invalidate(). Методы repaint () и revalidate () ставят в очередь запросы к потоку диспетчеризации событий для вызова paint () и validate () соответственно.

Это соответствует моему пониманию, но я не могу найти эту страницу или любую аналогичную страницу сейчас, и я видел неподтвержденные слухи от нескольких людей, которые говорили, что это больше не безопасно. Но с другой стороны, я не могу найти ничего определенного, говоря, что эта функция изменилась.

Изменить заметки

Что может помочь решить этот вопрос, так это официальное заявление от Oracle об изменениях в обработке потоков Swing. Я нашел страницу "Изменения в Java 7", но она вообще не упоминала об этом, ни одна из этих страниц никоим образом не упоминает многопоточность или 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

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

И repaint Метод не "документирует иначе".

Чтобы вдвойне заверить вас в том, что вам не нужно искать более подробный ответ, чем Javadoc отдельного метода, посмотрите, например, как безопасность потока метода была задокументирована в Java 6 Javadoc.

Обновить

По-видимому, необходимы дополнительные разъяснения относительно различия между нормативной спецификацией, описательными техническими статьями и деталями любой конкретной реализации. Что заявляет Javadoc: нет никакой гарантии, что repaint это потокобезопасный метод. Кстати, часто обсуждаемое в Java 7 решение об удалении "многопоточного" обозначения из большей части Swing API заключалось лишь в следующем: изменение договора, а не реализация.

Конкретная реализация repaint в OpenJDK 7 представляется поточно-ориентированным, что не имеет ничего общего с гарантиями, данными в спецификации. Код, который опирается на безопасность потока repaint или другие методы не работают и не гарантируется правильное поведение во всех реализациях Java.

Как обсуждено в Живописи в AWT и Swing: Обработка краски,

JComponent.repaint() регистрирует асинхронный запрос на перерисовку для компонента RepaintManager, который использует invokeLater() поставить в очередь Runnable чтобы позже обработать запрос в потоке диспетчеризации событий.

Это необходимое, но не достаточное условие для установления отношения " до того, как произойдет", между последовательными вызовами repaint(), На практике вам все равно нужно синхронизировать доступ к любым данным, которые совместно используются потоками. Без этого невозможно обеспечить видимость любых изменений, которые могут повлиять на последующий вызов repaint(),

Я бы сказал, что это все еще потокобезопасно. Метод repaint() не меняет свойства любого компонента Swing.

Метод repaint() вызывает RepaintManager. RepaintManager затем (потенциально) объединит несколько запросов рисования в один запрос рисования. Затем он добавит запрос краски в EDT для обработки.

Другие вопросы по тегам