Почему мои потоки SwingWorker продолжают работать, даже если они выполнены?
Я использую GUI для консольного приложения, и мне нужно выполнить некоторые действия (например, проанализировать XML файл) за указанный промежуток времени. Я решил использовать javax.swing.Timer вместе с SwingWorker, чтобы быть уверенным, что эти действия не сделают мое приложение невосприимчивым.
Я использовал таймер таким образом:
public class DataUpdateTimer extends Timer {
private String dataFlowControllerXML = null;
private DataUpdateWorker dataUpdateWorker = null;
public class DataUpdateWorker extends SwingWorker {
private String dataFlowControllerXML = null;
DataUpdateWorker(String dataFlowControllerXML) {
super();
this.dataFlowControllerXML = dataFlowControllerXML;
}
@Override
protected Boolean doInBackground() throws Exception {
Thread.sleep(300);
return Boolean.TRUE;
}
}
public class DataUpdateIntervalListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
DataUpdateTimer timer = (DataUpdateTimer)e.getSource();
DataUpdateWorker dataUpdateWorker = timer.getDataUpdateWorker();
if (dataUpdateWorker != null)
if (dataUpdateWorker.isDone()) {
Boolean updateResult = Boolean.FALSE;
try {
updateResult = (Boolean)dataUpdateWorker.get();
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
}
dataUpdateWorker = null;
}
// Creating new worker thread here
if (dataUpdateWorker == null) {
timer.dataUpdateWorker = new DataUpdateWorker(timer.dataFlowControllerXML);
// Starting a new worker thread for parsing Data Flow Controller XML
timer.dataUpdateWorker.execute();
return;
}
}
}
DataUpdateTimer(Integer dataUpdateInterval, String dataFlowControllerXML) {
super(dataUpdateInterval.intValue(), null);
this.dataFlowControllerXML = dataFlowControllerXML;
addActionListener(new DataUpdateIntervalListener());
}
@Override
public void stop() {
super.stop();
if (dataUpdateWorker != null) {
if (!dataUpdateWorker.isDone() || !dataUpdateWorker.isCancelled())
dataUpdateWorker.cancel(true);
}
}
}
... и используйте его следующим образом:
new DataUpdateTimer(1000, dataFlowControllerXML).start();
Все работает, как я желаю. Таймер создает новый экземпляр SwingWorker и выполняет его. После того, как работник завершен, создается и выполняется новый.
Я смущен тем, что после завершения рабочего потока я все еще вижу, что он работает в окне отладки Netbeans (например, как SwingWorker-pool-3-thread-1) или в диспетчере задач Windows ( количество выполняемых потоков не уменьшается после завершения потока). Количество потоков SwingWorker ограничено 10, но их запуск запутывает меня.
В случае простого использования потоков:
Thread th = new Thread(new Runnable() {
public void run() {
int a = 0;
}
});
th.start();
Этот поток автоматически исчезает после выполнения.
Является ли это поведение SwingWorker нормальным?
Ответы
Ответ 1
Да, это нормально. Как видно из названия нити, действия модели рабочего стола (фонового) персонала swing делегируются в пул потоков . Когда работа выполнена, поток возвращается в пул, и другой рабочий может его использовать. Это устраняет некоторые накладные расходы при создании/уничтожении потоков, которые могут быть дорогими.
Кстати, фоновые потоки не будут оставаться навсегда. Глядя на источник для SwingWorker
, я вижу:
//from SwingWorker.java (c) Sun Microsystems/Oracle 2009
executorService =
new ThreadPoolExecutor(1, MAX_WORKER_THREADS,
10L, TimeUnit.MINUTES,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
Это означает, что потоки будут отмирать после простоя в течение 10 минут.