У меня есть приложение, которое использует JTabbedPane для отображения нескольких разных вкладок. На одной из этих вкладок запущен поток для отображения ее содержимого. Я уже реализовал ComponentListener для остановки потока, когда вкладка не видна. Я вижу, как поток становится активным, когда выбрана вкладка, и останавливается, когда становится невидимым, как и ожидалось.
Если я закрываю свое приложение, когда вкладка с потоком не выбрана, все идет хорошо, и приложение закрывается. Если я закрываю свое приложение, когда вкладка с потоком видна, вкладка не получает ComponentEvent, поэтому поток остается активным, и мне нужно закрыть приложение вручную (используя кнопку «Завершить» на консоли в Eclipse).
Я предпочитаю не использовать метод System.exit() для закрытия моего приложения, а скорее останавливать все потоки и удалять все окна. Это работает как шарм, за исключением этой вкладки с нитью.
Я уже пытался сделать JTabbedPane невидимым перед удалением моего окна или removeAll(). Ни то, ни другое не дало ожидаемого результата. Метод removeAll() даже дал противоположный результат. Если вкладка не была активной, она получит ComponentEvent, указывающий, что она стала видимой (componentShown) (фактически, все вкладки получат событие по очереди, но ни одна из них не получит componentHidden).
Очевидно, что поток должен быть остановлен как при закрытии окна через меню файла (над которым у меня есть некоторый контроль и где я протестировал методы removeAll и setVisible(false)), так и когда окно удаляется, потому что пользователь щелкает на кресте в углу окна.
Обновить
Я нашел способ заставить поток, который, кажется, вызывает проблему, работать как поток демона, как было предложено. Однако это привело к неожиданной проблеме. Класс, который запустил проблемный поток, был классом VisRunner из программного пакета JUNG, который я использую. Он содержит метод «расслабиться», в котором запускается поток.
@Override
public void relax() {
// in case its running
stop();
stop = false;
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.start();
}
Я создал класс MyVisRunner:
import edu.uci.ics.jung.algorithms.layout.util.VisRunner;
import edu.uci.ics.jung.algorithms.util.IterativeContext;
public class MyVisRunner extends VisRunner {
public MyVisRunner(final IterativeContext process) {
super(process);
}
@Override
public void relax() {
// in case it's running
Log.d("Relaxing");
stop();
stop = false;
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.setDaemon(true);
thread.start();
}
}
Загружаю релаксатор так:
visModel = new DefaultVisualizationModel<>(layout);
visModel.setRelaxer(new MyVisRunner(layout));
Я ожидал, что это решит проблему, но это только усугубляет проблему. Когда я сейчас запускаю свой софт, он не останавливается, даже когда проблемная вкладка даже не видна (вкладка построена, но не видна). В этом случае метод Relax из MyVisRunner даже не вызывается; поток не инициализируется больше нигде в классе VisRunner. Комментирование строки setRelaxer решит эту дополнительную проблему (очевидно, сохранив исходную проблему).
Обновление 2
Я решил проблему наконец. Я не осознавал, что когда я устанавливал свой собственный релаксатор, он уже работал. Я изменил код на:
visModel = new DefaultVisualizationModel<>(layout);
visModel.getRelaxer().stop();
visModel.setRelaxer(new MyVisRunner(layout));
Это решило как дополнительную проблему, так и мою первоначальную.
Thread.setDaemon(true)
? - person oliholz   schedule 26.02.2013VisRunner
? Вы можете остановить Relaxer вручную,myDefaultVisualizationModel.getRelaxer().stop()
- person oliholz   schedule 26.02.2013