Объяснение потока обработки событий Java

Недавно я начал изучать и изучать основы программирования GUI на Java.

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

Я использую Swing и, насколько я могу понять, это означает, что я также использую AWT.

Мой вопрос основан на этом фрагменте кода:

java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
        new frame.setVisible(true);
    }
} );

Я изучал это некоторое время, так как хотел полностью понять этот странный фрагмент кода и несколько раз встречал термин "поток обработки событий". Поправь меня, если я не прав, но насколько я понимаю; это связано с использованием нескольких потоков и с тем, как Java Swing интерпретирует эти потоки. Я также понял, что приведенный выше код используется, чтобы убедиться, что все потоки "безопасны", прежде чем он создаст окно, следовательно, invokeLater?

Я прочитал это:

"Вы можете вызывать только те методы, которые работают с кадром, из потока диспетчеризации событий"

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

Может кто-нибудь объяснить мне, что именно представляет собой ветка диспетчеризации событий?

Как это относится к нескольким потокам выполнения и как эти потоки небезопасно вызывать из основного метода? Также зачем нам этот invokeLater?

Можем ли мы не просто создать окно, как любой другой объект?

В своем исследовании я натолкнулся на препятствие, так как не понимаю эти отношения и идеи.

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

Спасибо.

2 ответа

Решение

Поток EventDispatching - это специальный поток, которым управляет AWT. По сути это поток, который выполняется в событии обработки бесконечного цикла. Метод java.awt.EventQueue.invokeLater - это особый способ предоставления некоторого кода, который будет выполняться в очереди событий. Написание среды пользовательского интерфейса, которая безопасна в среде с многопоточностью, очень сложно, поэтому авторы AWT решили, что они будут разрешать операции над объектами GUI только в одном специальном потоке. Все обработчики событий будут выполняться в этом потоке, и весь код, который изменяет графический интерфейс, должен также работать в этом потоке.

Теперь AWT обычно не проверяет, что вы не запускаете команды gui из другого потока (среда WPF для C# делает это). так что можно написать много кода и быть в значительной степени агностиком к этому и не сталкиваться с какими-либо проблемами. Но это может привести к неопределенному поведению, поэтому лучше всего всегда следить за тем, чтобы код GUI выполнялся в потоке диспетчера событий. invokeLater предоставляет механизм для этого.

Итак, классический пример - вам нужно запустить длительную операцию, такую ​​как загрузка файла. Таким образом, вы запускаете поток для выполнения этого действия, а затем, когда оно будет завершено, вы будете использовать invokeLater для обновления пользовательского интерфейса. Если вы не использовали invokeLater и вместо этого просто обновили пользовательский интерфейс напрямую, у вас может возникнуть состояние гонки и может возникнуть неопределенное поведение.

В Википедии есть больше информации: http://en.wikipedia.org/wiki/Event_dispatching_thread

Также, если вам интересно, почему авторы awt не просто делают многопоточный инструментарий, вот хорошая статья: https://community.oracle.com/blogs/kgh/2004/10/19/multithreaded-toolkits-failed-dream

EventDispatchThread (EDT) - это специальная тема, зарезервированная только для графического интерфейса Swing и связанных с * событий Swing, например, создание / изменение / обновление Swing JComponents, больше для задаваемых вопросов здесь и здесь

весь вывод в графический интерфейс от BackGround Tasks, Runnable#Thread должен быть включен в invokeLater() из синхронизированных объектов в invokeAndWait();

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