Является ли javax.swing.SwingUtilities.invokeLater необходимым?

Так что я видел бесчисленное множество различных учебных пособий по GUI, и все они сказали использовать этот код:

   public static void main(String[] args) {
     javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });

}

И хотя я, возможно, не совсем понимаю, что именно это делает, так как я несколько новичок в GUI, я понимаю основы того, что он делает... или так я думал. Но потом я, в качестве эксперимента, вырезал все это и просто ушел:

   public static void main(String[] args) {
     createAndShowGUI(); 
   }

И это оказалось работать. Итак, теперь у меня есть вопрос: какова цель сохранить первый кусок кода, который у меня был, а не просто использовать второй, когда казалось, что второй работает так же хорошо? Если это необходимо, что произойдет, если я не буду его использовать?

1 ответ

Решение

Короче говоря, да, это необходимо всякий раз, когда вы вносите изменения в любой объект Swing (если API не говорит, что они являются потокобезопасными).

Любые изменения, которые вы вносите в графический интерфейс, должны быть сделаны в потоке диспетчеризации событий (EDT), поскольку объекты Swing не являются поточно-ориентированными. Из учебника по рассылке событий

Код обработки событий Swing выполняется в специальном потоке, известном как поток диспетчеризации событий. Большая часть кода, который вызывает методы Swing, также выполняется в этом потоке. Это необходимо, поскольку большинство методов объекта Swing не являются "поточно-ориентированными": их вызов из нескольких потоков может привести к помехам потоков или ошибкам согласованности памяти. Некоторые методы компонента Swing помечены как "потокобезопасные" в спецификации API; их можно безопасно вызывать из любого потока. Все остальные методы компонента Swing должны вызываться из потока диспетчеризации событий. Программы, которые игнорируют это правило, могут работать правильно большую часть времени, но подвержены непредсказуемым ошибкам, которые трудно воспроизвести.

Вызов SwingUtilities.invokeLater гарантирует, что код, который он запускает, вызывается в EDT, и вы не получите странных ошибок. Вот почему, когда вы удалили этот код, похоже, что все работает, потому что в ситуациях, которые вы тестировали, это возможно. Но это может не всегда, и вы не хотите иметь код, который иногда работает или имеет проблемы с синхронизацией.

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