Остановите ВСЕ потоки, мониторы и прочее Awt / Swing, чтобы остался только основной поток - PullRequest
3 голосов
/ 08 декабря 2011

У меня есть следующее

public static void main(String[] args) {
    boolean running = true;
    boolean foo= false;

    while(running)
    {
        doSomeTask(); // might set foo true
        if(foo) {
            //This call waits/blocks until gui is done working.
            fireUpSwingGui(); //does work...
            foo=false;
            godModeReleaseGUIandALLResourcesOnlyWantMainThreadLeft();
        }
    }
}

Надеюсь, что godModeReleaseGUIandALLResourcesOnlyWantMainThreadLeft() говорит само за себя.

Помните, что мы можем снова запустить графический интерфейс на более поздней стадии, когда fooснова становится true где-то внутри doSomeTask().

Ответы [ 2 ]

6 голосов
/ 08 декабря 2011

Взгляните на Проблемы с потоками AWT , в которых объясняются критерии выхода из приложения AWT.Вот часть, на которой вы хотите сосредоточиться:

Следовательно, автономное приложение AWT, которое желает завершить работу без вызова System.exit, должно:

  • Makeубедитесь, что все компоненты AWT или Swing отключены после завершения работы приложения.Это можно сделать, вызвав Window.dispose во всех Windows верхнего уровня.См. Frame.getFrames .
  • Убедитесь, что ни один из методов прослушивателей событий AWT, зарегистрированных приложением с любым компонентом AWT или Swing, не может работать в бесконечном цикле или зависать бесконечно.Например, метод прослушивателя AWT, вызванный некоторым событием AWT, может отправить новое событие AWT того же типа в EventQueue.Аргумент заключается в том, что методы прослушивателей событий AWT обычно выполняются на вспомогательных потоках.

Быстрый пример приложения для демонстрации ...

import java.awt.Frame;

import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

public class CloseAWT
{
    private static boolean running = true;
    private static int response = -1;

    public static void main(String[] args)
    {
        boolean showSwing = true;
        boolean checkFrames = true;
        while (running)
        {
            if (showSwing)
            {
                SwingUtilities.invokeLater(new Runnable()
                {
                    public void run()
                    {
                        response = JOptionPane.showConfirmDialog(null, "Hello World?");
                    }
                });
                showSwing = false;
            }
            else
            {
                if (response >= 0 && checkFrames)
                {
                    SwingUtilities.invokeLater(new Runnable()
                    {
                        public void run()
                        {
                            // topFrame.dispose();
                            Frame[] frames = Frame.getFrames();
                            System.out.printf("frames.length=%d\n", frames.length);
                        }
                    });
                    checkFrames = false;
                }
            }
        }
    }
}

Для подтверждения поведениябыло как положено, я запустил это в JProfiler.После нажатия «да», чтобы закрыть диалоговое окно подтверждения, поток «AWT-EventQueue-0» был помечен как мертвый.Единственные потоки, живущие после этого, были 'main' и потоком, который слушает Ctrl-Break.

Я настоятельно рекомендую использовать что-то вроде JProfiler , YourKit , JProbe или один из бесплатных профилировщиков, чтобы убедиться, что вы правильно выпустили всекомпоненты и удалили все прослушиватели.

Еще одна заключительная мысль ... Возможно, вы захотите создать свой GUI как отдельный процесс и использовать какой-то IPC для передачи информации между вашим процессом-демоном и GUI.Хотя это влечет за собой дополнительные накладные расходы на дополнительный процесс и IPC, это даст вам большую уверенность в том, что ваш GUI полностью очищен, когда он больше не нужен.

1 голос
/ 08 декабря 2011

Если вы открываете JFrame isntances, почему бы вам просто не сохранить их в коллекции, а внутри godModeReleaseGUIandALLResourcesOnlyWantMainThreadLeft() вы перебираете их и вызываете setVisible(false);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...