Интересно, как java SwingWorker и пул потоков работает, когда некоторая задача выполняется повторно. Вот SSCCE проблемы, готовой скопировать + паста:SwingWorker thread reusability
package com.cgi.havrlantr.swingworkerexample;
import java.awt.*;
import javax.swing.*;
public class Main extends JFrame {
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Main().setVisible(true);
}
});
}
public Main() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setSize(new Dimension(100,100));
JButton btn = new JButton("Say Hello");
add(btn);
btn.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnPressed(evt);
}
});
}
private void btnPressed(AWTEvent e) {
SayHelloSwingWorker worker = new SayHelloSwingWorker();
worker.execute();
}
private class SayHelloSwingWorker extends SwingWorker<Integer, Integer> {
protected Integer doInBackground() throws Exception {
System.out.println("Hello from thread " + Thread.currentThread().getName());
return 0;
}
}
}
Я хочу спросить о следующем. Каждый раз, когда я вызываю execute() в новом экземпляре рабочего (после нажатия кнопки), создается новый поток в пуле потоков SwingWorker до 10 созданных потоков. После превышения этого предела потоки повторно используются, как я ожидаю. Поскольку новые рабочие создаются последовательно после того, как предыдущий закончен, я не понимаю, почему первый поток не используется повторно, потому что предыдущий работник уже выполнил его работу. Скажем, может быть только один поток, который выполняет некоторые работы в то время. Я бы ожидал, что пул потоков создаст только один поток, который достаточно для выполнения всех задач. Это обычное поведение? Или может быть что-то неправильно, что отрицает повторное использование первого потока и заставляет поток пула создавать другой?
Если это нормально, я думаю, что это пустая трата времени для создания ненужной нити и памяти для поддержания готовности потоков. Можно мне это как-то избежать? Могу ли я заставить SwingWorker иметь только один поток в своем пуле? - Я думаю, нет, потому что количество потоков является постоянным и зависит от реализации Java, насколько я знаю.
Могу ли я заставить SwingWorker завершить поток после завершения задачи? (вызов this.cancel() в done() метод не работал)
Вот код моего реального рабочего мира, так как существует некоторая зависимость, которая может вызвать проблему.
public class MapWorker extends SwingWorker<Long, Object> {
@Override
protected Long doInBackground() throws Exception{
try {
long requestId = handleAction();
return requestId;
}catch(Exception e){
logger.error("Exception when running map worker thread.", e);
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
requestFinished();
}
});
MapUtils.showFatalError(e);
}
return -1l;
}
@Override
protected void done(){
try{
requestId = get();
logger.info("Returned from map request call, ID: {}", Long.toString(requestId));
}catch(InterruptedException e){
logger.error("Done interrupted - wierd!", e);
}catch(ExecutionException e){
logger.error("Exception in execution of worker thread.", e);
}
}
В методе handleAction() новый поток с некоторым блокирующим вызовом создается и идентификатор потока возвращается, что не должно быть ничего странно. Не спрашивайте меня, почему, это не мой код. :)
для лучшей помощи скорее отправить сообщение SSCCE, – mKorbel
[профиль] (http://stackoverflow.com/q/2064427/230513), чтобы проверить ожидания; нет необходимости в 'invokeLater()'; 'done()' работает на EDT. – trashgod
и [я надеюсь, что не похоже на] (http://stackoverflow.com/q/14900697/714968) – mKorbel