Объяснение потока диспетчеризации событий Java
недавно я начал изучать и изучать основы программирования GUI на Java.
некоторое время я программировал только бэкэнд-работу или работу, и в результате ближе всего к пользовательским интерфейсам я получил командную консоль (неловко, я знаю).
Я использую Swing и, насколько я могу собрать, это означает, что я также использую AWT.
мой вопрос основан на этом фрагменте кода:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new frame.setVisible(true);
}
} );
Я исследуя это некоторое время, поскольку я хотел полностью понять этот странный фрагмент кода и несколько раз сталкивался с термином "поток диспетчеризации событий". Исправьте меня, если я ошибаюсь, но как я понимаю; это связано с использованием нескольких потоков и как Java Swing интерпретирует эти потоки. Я также понимаю, что приведенный выше код используется, чтобы убедиться, что все потоки "безопасны", прежде чем он создаст окно, следовательно, invokeLater?
Я прочитал это:
"вы можете вызывать только методы, которые работают на фрейме из потока диспетчеризации событий"
и только при определенных обстоятельствах вы можете вызывать методы, которые работают на фрейме из метода main.
может кто-нибудь уточнить мне, что именно такое поток отправки событий?
как это относится к нескольким потокам выполнения и как эти потоки небезопасны для вызова из основного метода? Также зачем нам этот invokeLater?
можем ли мы не просто создать окно как любой другой объект?
Я попал немного в дорожный блок в своих исследованиях, поскольку я не понимаю этих отношений и идей.
боковое замечание заключается в том, что мне нравится основывать свои знания на глубоком понимании, поскольку я считаю, что это приводит к лучшему общему результату и, как результат, лучшим программам. Если я глубоко понимаю, как что-то работает, вы можете использовать советы и твики эффективно, а не просто повторять их обратно в код, поэтому, пожалуйста, не бойтесь дать мне дополнительные подробные объяснения и расширить мои знания.
спасибо.
2 ответов
поток EventDispatching-это специальный поток, управляемый AWT. В основном это поток, который работает в бесконечном цикле обработки событий. Ява.ОУ.EventQueue.метод invokeLater-это специальный способ предоставить код, который будет выполняться в очереди событий. Написать UI framework, который безопасен в многопоточном окружении, очень сложно, поэтому авторы AWT решили, что они разрешат операции с объектами GUI происходить только в одном специальном потоке. Все мероприятие обработчики будут выполняться в этом потоке, и весь код, который изменяет gui, также должен работать в этом потоке.
теперь AWT обычно не проверяет, что вы не выдаете команды gui из другого потока (платформа WPF для C# делает это). таким образом, можно написать много кода и быть в значительной степени агностиком к этому и не столкнуться с какими-либо проблемами. Но это может привести к неопределенному поведению, поэтому лучше всего всегда гарантировать, что код gui работает на диспетчере событий нитка. invokeLater предоставляет механизм для этого.
таким образом, классический пример заключается в том, что вам нужно запустить длительную операцию, такую как загрузка файла. Таким образом, вы запускаете поток для выполнения этого действия, а затем, когда он будет завершен, вы будете использовать invokeLater для обновления пользовательского интерфейса. Если вы не использовали invokeLater и вместо этого просто обновили пользовательский интерфейс напрямую, у вас может возникнуть состояние гонки и неопределенное поведение.
Wikipedia имеет более подробную информацию: http://en.wikipedia.org/wiki/Event_dispatching_thread
также, если вам интересно, почему авторы awt не просто делают инструментарий многопоточным, вот хорошая статья: https://community.oracle.com/blogs/kgh/2004/10/19/multithreaded-toolkits-failed-dream
EventDispatchThread
(EDT) - специальный поток, зарезервированный только для GUI Swing и связанных с ним событий *Swing, например, create/change/update Качели JComponents, больше для задаваемых вопросов здесь и здесь
все выходные данные в GUI от BackGround Tasks
, Runnable#Thread
должно быть заключено в invokeLater(), из синхронизированных объектов в invokeAndWait();