Объясните, что делает следующий код?

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

пожалуйста, скажите мне, что делает вышеуказанный код на самом деле. Я ищу строчку за строчкой объяснения. особенно первая строка и скажите мне, почему мы используем это и в каких сценариях мы должны использовать это.

5 ответов


в этом примере вы видите anyonmous класс, производный от Runnable. Этот анонимный класс переопределяет метод run интерфейса runnable. Затем этот анонимный класс создается и передается EventQueue.метод invokeLater, который является статическим методом. Этот метод добавляет объект... что ж... в eventQueue. В EvenQueue много событий, таких как события клавиатуры или мыши или что-то еще. Существует поток, который непрерывно опрашивает данные из этой очереди. Однажды эта нить достигает анонимного класса, который был создан здесь, он выполнит метод run (), который создаст экземпляр объекта класса NewJFrame и установит его видимым.

весь смысл этого сложного заключается в том, что новый JFrame().часть setVisible (true) выполняется не в основном потоке, а в потоке диспетчеризации событий. В Swing необходимо выполнить весь код, который изменяет пользовательский интерфейс в потоке диспетчеризации событий.


однопоточная модель и EDT

большинство современных библиотек UI принимают single-thread-model. Это означает, что все манипуляции с компонентами пользовательского интерфейса должны выполняться в одном потоке. Почему? Это потому, что разрешение компонентов пользовательского интерфейса обновляться из нескольких потоков приведет к хаосу, так как большинство методов объектов Swing не являются "потокобезопасными". Для простоты, эффективности и робастности, одиночн-поток-модель принята.

в качели, очень нить, которая служит single-thread-model называется Поток Диспетчеризации Событий, т. е. EDT. Это не предусмотрено ходом. Это предусмотрено Абстрактное Окно Toolkit, т. е. АВТ.

рабочий поток vs UI thread

нетривиальное приложение GUI обычно имеет много потоков. В современном приложении GUI может быть много рабочих потоков для грязной работы, но есть единственный UI thread (Swing называет его EDT) для обновления ГРАФИЧЕСКИЙ ИНТЕРФЕЙС ПОЛЬЗОВАТЕЛЯ. Рабочие потоки обычно должны отражать ход своей работы в GUI, поэтому им нужно общаться с потоком пользовательского интерфейса об этом. Так как же происходит это общение?

java.ОУ.EventQueue

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

основной поток

ваш фрагмент кода обычно находится в main() нить,main поток можно рассматривать как своего рода worker thread здесь. Только это вместо обновления GUI путем публикации сообщений в EventQueue, он инициирует GUI. Во всяком случае, инициацию можно рассматривать как работа тоже.

после того, как GUI будет инициирован, основной поток выйдет, и EDT предотвратит выход процесса.

и еще одно хорошее объяснение:

Java Event-диспетчеризация потока объяснение

интересные статьи: многопоточный инструментарий, сбой сон?


это блок кода, который поручил выполнить в более позднее время (иногда называемый отложить). Внутренний класс (new Runnable() {...}) - Это по существу позволяет передать блок кода, который будет выполняться. The invokeLater метод гарантирует, что блок кода будет запущен, но не гарантирует, когда. Иногда небезопасно, чтобы определенный код запускался сразу, и его слишком многословный, чтобы делать многопоточность самостоятельно. Таким образом, Java предоставляет этот метод утилиты безопасно выполнять код. Код будет запущен очень скоро, но не раньше, чем это будет безопасно.


на invokeLater вызов помещает указанный runnable в очередь, которая будет обработана позже. То есть код внутри run() метод еще не будет запущен, когда invokeLater возвращает вызов метода.

существует два типичных варианта использования для этого типа кода.

  1. текущий код выполняется в фоновом потоке. Фоновые потоки не могут получить доступ к большинству API swing. Подробнее здесь по этой причине. Если тока поток уже является потоком пользовательского интерфейса, нет причин, и вызов можно безопасно удалить.
  2. необходимо выйти из текущего блока, т. е. код достигнет последней скобки. Это может привести к высвобождению ресурсов и так далее. Это не так распространено.

анонимный класс передается в качестве параметра invokeLater звонок. Это то же самое, что и этот код.

private void foo()
{
  java.awt.EventQueue.invokeLater(new JFrameCreator());
}
private class JFrameCreator implements Runnable
{
  public void run() {
    new NewJFrame().setVisible(true);
  }
}

источник

метод invokeLater () принимает в качестве параметра объект Runnable. Он отправляет этот объект в поток диспетчеризации событий, который выполняет метод run (). Вот почему метод run() всегда безопасен для выполнения кода Swing.

-IvarD