2012-06-01 4 views
4

Почему этот код заморозит мое приложение Swing? Компоненты Swing находятся в отдельном потоке из моего потока InfiniteLoop. Если перед каждой печатью я представлю сон в методе run(), то программа работает нормально. Есть ли у кого-нибудь какие-либо подсказки?Swing Замораживает при возникновении отдельной нити

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGUI(); // <-- creates the swing frame and component 
     } 
    }); 

    Thread t = new Thread(new InfiniteLoop()); 
    t.start(); 
} 

public class InfiniteLoop implements Runnable 
{ 
    private static Logger logger = Logger.getLogger(InfiniteLoop.class); 
    public void run() 
    { 
     while(true) 
     { 
       log.info("test"); 
     } 
    } 
} 
+0

Чтобы лучше помочь, опубликуйте [SSCCE] (http://sscce.org/). –

+0

@AndrewThompson - Просто любопытно - разве это не то, что он сделал? –

+0

@KevinDay No. SSCCE проблемы времени выполнения должен быть единственным исходным файлом, который можно скопировать, вставить, скомпилировать (с 0 изменениями), запустить и показать проблему. Поскольку мы имеем части двух классов без импорта -> не SSCCE. –

ответ

3

Ответ здесь должен сделать с реализацией планирования потоков в Java (или, скорее, специфика реализации планирования потоков Java для вашей платформы). Большинство реализаций потоковой передачи Java завершают работу заданного потока (на заданном уровне приоритета), пока поток не войдет в условие ожидания. Затем выполняется следующий поток на этом уровне приоритета и т. Д. Обратите внимание, что спецификация JVM не указывает точное поведение - это зависит от того, какой разработчик JVM должен решить.

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

Вот an article, который описывает это немного.

Как потенциальная утонченность: вызов invokeLater() может привести к тому, что запуск runnable в очереди, который никогда не имеет возможности перечеркнуть, потому что ваш фоновый поток принимает весь процессор. Интересный эксперимент состоял бы в том, чтобы переместить запуск вашего фонового потока в Runnable - это дало бы EDT возможность инициализации до того, как ваш фоновый поток начнет потреблять процессор.

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGUI(); // <-- creates the swing frame and component 

      Thread t = new Thread(new InfiniteLoop()); 
      t.start(); 
     } 
    }); 

} 

или даже:

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      Thread t = new Thread(new InfiniteLoop()); 
      t.start(); 

      createAndShowGUI(); // <-- creates the swing frame and component 
     } 
    }); 

} 

Я бы на самом деле быть заинтересованы в результатах этого (не достаточно заинтересованы, чтобы на самом деле проверить это, хотя :-)). Некоторые ссылки, которые я вижу в Интернете, говорят о том, что по умолчанию EDT работает на более высоком уровне приоритета (в этом случае сам EDT не должен испытывать голод). Если вы начинаете фоновый поток изнутри EDT, интерфейс Swing остается отзывчивым?

+0

Этот ответ лучше моего. 1+ Кевину, и я удалю свой более слабый ответ. –

+0

Бах - есть много способов кожи этого кота. Для чего это стоит, я посмотрел * hard *, чтобы узнать, что такое приоритет по умолчанию EDT, и не смог найти ссылку, в которой он был указан. На самом деле я был бы немного удивлен, если EDT еще не работает с более высоким приоритетом, но сброс приоритета рабочего потока наверняка кажется лучшим первым шагом. Мы можем обнаружить, что мой ответ (в то время как технически точный) делает приседания стоящей разницей в специфике вопроса. –

+0

очень плохой ответ, действительно, никогда, не начинайте Thread из invokeLater когда-либо, это один из способов, как убить EDT, откуда вы знаете, что внутри Thread, или что потенциал Swing GUI, ожидающий окончания Thread, aaaachh – mKorbel

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