2011-02-05 7 views
15
java.awt.EventQueue.invokeLater(new Runnable() { 
    public void run() { 
     new NewJFrame().setVisible(true); 
    } 
}); 

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

ответ

27

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

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

+0

вы сделали хорошую работу, и я ясно с этими понятиями теперь !! спасибо .. – Deepak

+0

И что произойдет, если вы просто поместите это в основной метод, без какой-либо обертывания? 'public static void main (String args []) {New JFrame(). SetVisible (true);}' – Martin

+1

@Martin: Затем вы нарушаете правило, что код, который влияет на пользовательский интерфейс, должен быть выполнен в потоке диспетчеризации события. Это может случиться (в большинстве случаев), но может также вызвать ряд ошибок, связанных с условиями гонки и т. Д. Трудно предсказать, что может произойти. Возможно, вы столкнулись с ошибками рисования, может быть, и нет. – yankee

2

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

+1

у вас есть хороший контент, и я понял, что ссылка invokeLater хорошо. – Deepak

1

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

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

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

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

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

это хорошее объяснение .. просто скажите мне, почему мы используем runnable() здесь ?? – Deepak

+0

и я думаю (новый JFrameCreator()) создаст анонимный класс. Означает ли это, что когда этот поток обрабатывается, run() запускается автоматически. Прошу прощения, если я прошу что-то совершенно неправильное. Я просто хочу знать о run() и (новый JFrameCreator()). – Deepak

+0

Нет, извините, но это не сработает. Класс JFrameCreator ДОЛЖЕН реализовать Runnable (только класс записи JFrameCreator реализует Runnable). И @Deepak: Нет, в этом примере нет анонимного класса. – yankee

1

Source

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

-IvarD

4

Однозаходные-модель и EDT

Большинство современных библиотек UI принять single-thread-model.Это означает, что все манипуляции с компонентами пользовательского интерфейса ДОЛЖНЫ выполняться на одном и том же потоке. Зачем? Это связано с тем, что обновление компонентов пользовательского интерфейса из нескольких потоков приведет к хаосу с most Swing object methods are not "thread safe". Для простоты, эффективности и надежности применяется однопоточная модель.

В Swing самая нить, обслуживающая single-thread-model, называется Event Dispatching Thread, то есть EDT. Свинг не предоставляется. Он предоставляется Abstract Window Toolkit, то есть AWT.

рабочий поток UI против резьбы

Нетривиального приложение с графическим интерфейсом, как правило, имеет много потоков. В современном графическом приложении может быть много рабочих потоков для грязной работы, но есть только один поток UI (Swing называет его EDT) для обновления GUI. Рабочие потоки, как правило, должны отражать их прогресс в графическом интерфейсе, поэтому им необходимо обмениваться информацией с потоком пользовательского интерфейса. Итак, как происходит это общение?

java.awt.EventQueue

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

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

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

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

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

Java Event-Dispatching Thread explanation

Интересная статья: Multi-threaded toolkit, a failed dream?

+0

Похоже, что ваша последняя ссылка там сгнила или была неуместна? У вас есть ссылка на эту статью? Звучит интересно. – code11

+0

@ code11 Спасибо за указание. Ссылка обновлена. – smwikipedia

Смежные вопросы