Что такое поток рассылки событий? - PullRequest
6 голосов
/ 20 марта 2010

Я знаю, что означает "поток", и понимаю ли я поток обработки событий (EDT) как «просто нить», это многое объясняет, но, видимо, не все объясняет.

Я не понимаю, что особенного в этой теме. Например, я не понимаю, почему мы должны запустить графический интерфейс в EDT? Почему «основной» поток это кровать для GUI? Что ж, если мы просто не хотим занимать основной поток, почему мы не можем запустить GUI просто в «другом потоке», почему это должен быть какой-то «специальный» поток с именем EDT?

Тогда я не понимаю, почему мы не можем запустить EDT как любой другой поток? Почему мы должны использовать какой-то специальный инструмент (называемый invokeLater). И почему GUI, в отличие от любого другого потока, запускается не сразу. Мы должны подождать, пока он не будет готов принять нашу работу. Это потому, что EDT может потенциально выполнять несколько задач одновременно?

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

ДОБАВЛЕНО:

Я всегда думал, что у нас есть одно «задание» на поток. Итак, в каждом потоке мы выполняем предопределенную последовательность команд. Но мне кажется, что в ветке диспетчеризации событий у нас может быть серьезное задание. Ну, они не выполняются одновременно (поток переключается между различными задачами, но в одном потоке все еще есть несколько задач). Это правильно? Например, в EDT есть один поток, который отображает главное окно, а затем дополнительно к этому мы отправили в EDT еще одну задачу, которая должна обновить один из компонентов окна, и EDT выполнит эту новую задачу, когда она будет готова. Отличается ли EDT от других тем?

Ответы [ 4 ]

6 голосов
/ 20 марта 2010

Я всегда думал, что у нас есть один «задача» на поток. Итак, в каждой теме мы выполняем предопределенную последовательность команды. Но мне кажется, что в поток диспетчеризации событий мы можем есть серьезное задание. Ну, они не выполняется одновременно (поток переключается между различными задачами, но есть еще несколько задач в одном нить). Это правильно? Например есть одна нить в EDT, которая отобразить главное окно, а затем в дополнение к этому мы отправили EDT еще одна задача, которую следует обновить один из оконных компонентов и EDT будет выполнять эту новую задачу всякий раз, когда это готов. Отличается ли EDT от других темы таким образом?

Нет, EDT принципиально не отличается от других потоков. И «задача» не очень хорошее слово для использования, потому что его можно спутать с процессами уровня ОС (которые также часто называют задачей). Лучше использовать Runnable, интерфейс, используемый для передачи кода в EDT для выполнения через invokeLater().

EDT в основном связан с очередью вещей, которые он должен делать. Когда пользователь нажимает кнопку в графическом интерфейсе, в очередь входит Runnable, который уведомляет всех слушателей, прикрепленных к кнопке. Когда размер окна изменяется, Runnable, выполняющий revalidate & repaint, попадает в очередь. А когда вы используете invokeLater(), ваш Runnable попадает в очередь.

EDT просто запускает бесконечный цикл, который говорит: «возьмите Runnable из очереди (и если он будет пустым, пока вы не получите уведомление, что это не так) и выполните его.

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

6 голосов
/ 20 марта 2010

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

В связи с тем, что вам необходимо обновить графический интерфейс пользователя с invokeLater(), это связано с проблемами параллелизма. GUI может быть изменен только из одного потока, потому что Swing не является потокобезопасным (стоит отметить, что большинство наборов инструментов не являются потокобезопасными, есть хорошая статья , которая дает идеи почему). Вот почему вы должны отправить все обновления графического интерфейса для запуска на EDT.

Вы можете прочитать больше о параллелизме в Swing и потоке диспетчеризации событий в Учебник Sun по параллелизму в Swing . Кроме того, если вы хотите посмотреть, как это можно сделать по-другому, вы можете проверить SWT toolkit . В SWT вы должны сами управлять EDT.

3 голосов
/ 20 марта 2010

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

Итак, решение: вызывать методы Swing только из одного потока. Это поток EDT - он не является чем-то особенным, кроме того, что он предназначен для вызова методов колебания.

Теперь вы можете спросить, почему методы Swing не безопасны для потоков? После нескольких неудачных попыток разработчики GUI-инструментария обнаружили, что по сути невозможно разработать поточно-ориентированный GUI-инструментарий. Слишком часто события передаются в противоположных направлениях (входные события снизу вверх, события приложения сверху вниз), что всегда приводит к взаимоблокировкам. Так что так оно и есть.

3 голосов
/ 20 марта 2010
What is the EDT?

Это хакерский обходной путь для решения множества проблем параллелизма, которые есть в Swing API;)

Серьезно, многие компоненты Swing не являются "потокобезопасными" (некоторые известные программисты даже называли Swing "враждебным потоком"). Наличие уникального потока, в котором все обновления выполняются для компонентов, враждебных по отношению к потоку, позволяет избежать многих потенциальных проблем параллелизма. В дополнение к этому вы также гарантируете, что он будет запускать Runnable, который вы проходите через него, используя invokeLater в последовательном порядке.

Обратите внимание, что дело не только в том, что вы уклоняетесь от проблемы параллелизма: вы должны соблюдать рекомендации Sun относительно того, что должно и что не должно быть сделано в EDT, иначе у вас возникнут серьезные проблемы в вашем приложении. .

Другое преимущество состоит в том, что некоторые компоненты Swing имеют тенденцию генерировать нежелательные исключения, и когда это происходит, они автоматически обрабатываются и не приводят к аварийному завершению EDT (AFAIK, если вам действительно удастся уничтожить EDT, он автоматически перезапускается). *

Другими словами: вам не нужно иметь дело со всеми сломанными компонентами Swing и исключениями, которые они сами себе выдают: об этом позаботится EDT (просто взгляните на бесчисленные ошибки Swing, выбрасывающие исключения в параде ошибок Sun) , это увлекательно ... И все же большинство приложений продолжают работать нормально).

Кроме того, выполнение только того, что является обязательным в EDT, позволяет графическому интерфейсу вашего приложения оставаться «отзывчивым», даже если в фоновом режиме выполняются задачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...