Объяснение потока обработки событий Java - PullRequest
53 голосов
/ 28 августа 2011

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Спасибо.

Ответы [ 2 ]

58 голосов
/ 28 августа 2011

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

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

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

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

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

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

12 голосов
/ 28 августа 2011

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

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

...