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

Объяснение объяснения Java Event-Dispatching

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

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

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

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

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

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

Я читал, что:

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

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

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

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

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

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

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

Спасибо.

4b9b3361

Ответ 1

Поток отправки событий - это специальный поток, которым управляет AWT. По сути, это поток, который работает в бесконечном цикле, обрабатывая события.

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

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

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

Википедия имеет больше информации

Кроме того, если вам интересно, почему авторы AWT не делают многопоточный инструментарий, вот хорошая статья.

Ответ 2

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

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