Введение

Поток диспетчеризации событий (EDT) — это фоновый поток, используемый в Java для обработки событий из очереди событий графического пользовательского интерфейса Abstract Window Toolkit (AWT). Он является примером общей концепции событийного программирования, популярной во многих других областях, помимо Java, например, в веб-браузерах или веб-серверах. Событиями в основном являются события обновления, которые приводят к перерисовке компонентов пользовательского интерфейса, или события ввода от устройств ввода, таких как мышь или клавиатура. AWT использует модель однопоточной отрисовки, в которой все обновления экрана должны выполняться из одного потока. Поток диспетчеризации событий — единственный допустимый поток для обновления визуального состояния видимых компонентов пользовательского интерфейса. Обновление видимых компонентов из других потоков является причиной многих распространенных ошибок в Java-программах, использующих Swing. Поток диспетчеризации событий называется основным рабочим потоком в Adobe Flash и потоком пользовательского интерфейса в SWT, .NET Framework и Android.

Схема передачи сообщений для сериализации GUI-доступа

Программное приложение обычно состоит из нескольких потоков и одной структуры данных GIT. Это означает, что GIT является общей структурой данных и требуется некоторая синхронизация, чтобы гарантировать, что к ней одновременно обращается только один поток. Хотя AWT и Swing предоставляют (непотокобезопасные) методы для создания и доступа к компонентам графического интерфейса, и эти методы доступны всем потокам приложения, как и в других GUI-фреймворках, только один – поток диспетчеризации событий (EDT) – имеет право выполнять эти методы. Поскольку программисты часто упускают это требование, сторонние оформления, такие как Substance, доходят до того, что отказываются создавать какие-либо компоненты Swing, если выполнение не происходит в потоке диспетчеризации событий, чтобы предотвратить подобную ошибку в коде. Доступ к графическому интерфейсу сериализован, и другие потоки могут отправлять код для выполнения в EDT через очередь сообщений EDT. То есть, как и в других GUI-фреймворках, поток диспетчеризации событий проводит все свое время, обрабатывая сообщения: он поддерживает очередь сообщений с действиями, которые необходимо выполнить над графическим интерфейсом. Эти запросы отправляются в очередь системой и любым потоком приложения. EDT последовательно извлекает их и реагирует, обновляя компоненты графического интерфейса. Сообщения могут представлять собой известные действия или включать обратные вызовы – ссылки на пользовательские методы, которые должны быть выполнены с помощью EDT. Важным требованием ко всем сообщениям является их быстрое выполнение, чтобы графический интерфейс оставался отзывчивым. В противном случае цикл обработки сообщений блокируется, и графический интерфейс перестает отвечать.

Передача кода пользователя в EDT

Существуют различные способы отправки кода в EDT и выполнения длительных задач, не блокируя основной цикл.

Компонентные обработчики событий (слушатели)

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

Модель рабочего дизайна

Исполнение задачи в отдельном потоке и отображение результатов в EDT можно объединить с помощью шаблона проектирования "рабочий". Класс `javax.swing.SwingWorker`, разработанный Sun Microsystems, является реализацией этого шаблона и, начиная с Java 6, входит в стандартную поставку Swing. SwingWorker обычно вызывается из EDT через обработчик событий для выполнения длительной операции, чтобы не блокировать EDT.

Эквиваленты

System.ComponentModel.BackgroundWorker .NET Framework
flash.system.Worker Adobe Flash
android.os.AsyncTask Android