Что такое поток диспетчеризации событий?
Я знаю, что означает" поток", и если я понимаю поток диспетчеризации событий (EDT) как "просто нить", это многое объясняет, но, по-видимому, не все объясняет.
Я не понимаю, что особенного в этой теме. Например, я не понимаю, почему мы должны запускать GUI в EDT? Почему "основной" поток-это кровать для GUI? Ну, если мы просто не хотим занимать основной поток, почему мы не можем запустить GUI только в "другом потоке", почему это должно быть "специальная" нить под названием EDT?
тогда я не понимаю, почему мы не можем запустить EDT, как любой другой поток? Почему мы должны использовать какой-то специальный инструмент (называемый invokeLater
). И почему GUI, в отличие от любого другого потока, не запускается сразу. Мы должны подождать, пока он не будет готов принять нашу работу. Это потому, что EDT может потенциально выполнить несколько задач одновременно?
Если вы решите ответить на этот вопрос, не могли бы вы использовать очень простую терминологию, потому что в противном случае я боюсь, я не смогу понять ответ.
добавлено:
Я всегда думал, что у нас есть одна "задача" на поток. Итак, в каждом потоке мы выполняем предопределенную последовательность команд. Но мне кажется,что в случае диспетчеризации потока мы можем разорвать задачу. Ну, они не выполняются одновременно (поток переключается между разными задачами, но в одном потоке все еще есть несколько задач). Правильно ли это? Например, в EDT есть один поток которые отображают главное окно, а затем дополнительно к этому мы отправили в EDT другую задачу, которая должна обновить один из компонентов окна, и EDT выполнит эту новую задачу, когда она будет готова. Отличается ли EDT от других потоков таким образом?
4 ответов
поток диспетчеризации событий-это поток, который обрабатывает все события GUI и управляет вашим GUI Swing. Он запускается где-то в коде Swing, если у вас есть GUI в вашей программе. Причина, по которой это делается за кулисами, заключается в простоте - вам не нужно беспокоиться о запуске и управлении дополнительным потоком самостоятельно.
относительно того, что вам нужно обновить свой GUI с помощью invokeLater()
Это из-за проблем параллелизма. GUI может быть изменен только с одного поток, потому что Swing не является потокобезопасным(стоит отметить, что большинство из наборов инструментов не являются потокобезопасными, есть хорошая статья что дает некоторые идеи, почему). Вот почему вы должны отправить все обновления GUI для запуска на EDT.
вы можете прочитать больше о параллелизме в потоке Swing и диспетчеризации событий в Sun учебник по параллелизму в Swing. Кроме того, если вы хотите увидеть, как это можно сделать по-другому, вы можете проверить SWT toolkit. В SWT вы должны управлять EDT самостоятельно.
Я всегда думал, что у нас одна "задача" в потоке. Итак, в каждой нити мы выполняем предопределенную последовательность команды. Но мне кажется, что в поток диспетчеризации событий мы можем у север задача. Ну, это не так. выполняется одновременно (поток переключается между различными задачами, но есть еще несколько задач в одном нить.) Правильно ли это? Например в EDT есть один поток, который откройте главное окно, а затем в дополнение к этому мы отправлено EDT еще одна задача, которая должна обновляться один из компонентов окна и EDT будет выполнять эту новую задачу всякий раз, когда она готова. Отличается ли EDT от других нити таким образом?
нет, EDT принципиально не отличается от других потоков. И "задача" -не очень хорошее слово, потому что его можно спутать с процессами уровня ОС (которые также часто называют задачей). Лучше использовать Runnable
, интерфейс, используемый для предоставления кода EDT для выполнения через invokeLater()
.
EDT в основном связан с очередью вещей, которые он должен делать. Когда пользователь нажимает кнопку на GUI, a Runnable
который уведомляет всех слушателей, прикрепленных к кнопке, переходит в очередь. При изменении размера окна, а Runnable
выполнение revalidate & repaint входит в очередь. И когда вы используете invokeLater()
ваш Runnable
идет в очередь.
EDT просто запускает бесконечный цикл, который говорит: "Возьмите Runnable
из очереди (и если это пустой сон, пока вы не уведомил, что это не так) и выполнить его.
таким образом, он выполняет все эти маленькие Runnable
куски кода один за другим, так что каждый из них в основном имеет GUI все для себя во время работы, и не нужно беспокоиться о синхронизации ничего. Когда вы управляете GUI из другого потока, это предположение нарушается, и вы можете получить GUI в поврежденном состоянии.
What is the EDT?
это хакерский обходной путь вокруг большого количества проблем параллелизма, которые имеет API Swing;)
серьезно, многие компоненты Swing не являются " потокобезопасными "(некоторые известные программисты дошли до того, что назвали Swing"потокобезопасным"). Имея уникальный поток, в котором все обновления производятся для этих компонентов, враждебных потоку, вы уклоняетесь от многих потенциальных проблем параллелизма. В дополнение к этому вы также гарантируете, что он будет запускать Runnable, через который вы проходите он через invokeLater в последовательном порядке.
обратите внимание, что вы не просто уклоняетесь от проблемы параллелизма: вы должны соблюдайте рекомендации Sun относительно того, что должно и что не должно быть сделано на EDT, или у вас будут серьезные проблемы в вашем приложении.
еще одно преимущество заключается в том, что некоторые компоненты Swing имеют тенденцию создавать нежелательные исключения, и когда это происходит, они автоматически обрабатываются и не будут разбивать EDT (AFAIK, если вам действительно удастся убить EDT автоматически перезапускается).
другими словами: вам не нужно иметь дело со всеми сломанными компонентами качания и исключениями, которые они бросают сами: EDT заботится об этом (просто взгляните на бесчисленные ошибки качания, бросающие исключения в параде ошибок Sun, это увлекательно... И все же большинство приложений продолжают работать нормально).
кроме того, делая только то, что обязательно в EDT позволяет GUI вашего приложения оставаться "отзывчивым" даже жестким, могут быть задачи бег на заднем плане.
важно помнить, что классы Swing не являются потокобезопасными. Это означает, что вы всегда должны вызывать методы Swing из одного потока, или вы рискуете получить странное или неопределенное поведение.
Итак, решение: только вызовите методы Swing из одного потока. Это поток EDT - он не является особенным каким-либо образом, кроме того, что это поток, назначенный для вызова методов swing.
теперь вы можете спросить, почему методы Swing не являются потокобезопасными? После несколько неудачных попыток, дизайнеры GUI toolkit обнаружили, что по своей сути невозможно разработать потокобезопасный GUI toolkit. Слишком часто события передаются в противоположных направлениях (входные события снизу вверх, события приложения сверху вниз), что всегда приводит к тупикам. Так вот оно что.