Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

Это официальная ссылка :

Политика качания потоков

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

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

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

Update

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

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

Ответ 2

Как обсуждалось в Покраска в AWT и Swing: Paint Processing,

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

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

Ответ 3

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

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