Почему я должен использовать отдельный поток, чтобы показать графический интерфейс в JAVA

Эта простая проблема смущает меня. Вы можете отобразить приложение JAVA GUI, установив кадры setVisible имущество true, Но почти во всех примерах, которые я нашел в Интернете, они используют отдельный поток, чтобы сделать то же самое.

Они делают что-то вроде этого,

SwingUtilities.invokeLater(new Runnable() {

    @Override
    public void run() {
        new Frame().setvisible(true);  //just take the idea of this line
    }
});

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

Может кто-нибудь объяснить это.. спасибо!

6 ответов

Решение

Основной причиной запуска вашего приложения таким образом является то, что компоненты Swing не являются поточно-ориентированными, поэтому вам нужно гарантировать, с какого потока будет запускаться ваш графический интерфейс: тот, который называется Event Dispatching Thread (EDT). Без этого вы не можете быть уверены, в каком потоке он будет запущен, но, как отметили некоторые добрые комментаторы, основной поток гарантированно не будет EDT.

Вы должны только создавать, получать доступ или изменять компоненты пользовательского интерфейса из EDT. В противном случае вы столкнетесь с неожиданным поведением (если вам повезет) и / или с грязными перерисовками.

Некоторые ресурсы, с которыми я предлагаю вам ознакомиться:

Вы также можете прочитать о том, почему мое стандартное настольное Java-приложение JFrame использует EventQueue.invokeLater в основном методе?

ОБНОВИТЬ

Это блог, который я пытался найти:P

Это в основном объясняет, почему важно синхронизировать ваши main с EDT, прежде чем начать, он также описывает некоторые детали о том, почему.

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

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

Также обратите внимание, что то же самое верно для большинства других наборов инструментов GUI, таких как формы в.NET, MFC и других.

Swing не является потокобезопасным, и все компоненты должны быть инициализированы в EDT. Это предотвратит такие проблемы, как взаимоблокировка.

Потому что все изменения, которые вы делаете в GUI, должны выполняться в потоке диспетчеризации событий. Вот как должны работать AWT и SWING.

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

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

Без этого звонка, если вы только что позвонили setVisible(true) из любого старого потока, вы не будете иметь никакой безопасности потока и Frame может даже не увидеть действия этого метода. Что еще хуже, Frame мог видеть только некоторые из действий, нарушая внутренние предположения и инварианты и вызывая странное поведение, сбои или тупики.

Инфраструктура графического интерфейса Java разработана как единый поток для обеспечения безопасности потока: этот метод называется ограничением потока. Поэтому любая операция графического интерфейса, например создание компонентов, создание модели, отправленное событие и т. Д., Должна выполняться в потоке диспетчеризации событий (EDT). Способ, которым вы описываете, является одним из способов поставить операцию в очередь в EDT.

Другие вопросы по тегам