java SwingWorker线程可重用性
我想知道当重复执行某个任务时,java SwingWorker及其线程池是如何工作的。下面是问题的SSCE,准备复制+粘贴:
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;
}
}
}
我想问一下下面的问题。每次我在worker的一个新实例上调用execute()(在按下按钮之后),SwingWorker线程池中会创建一个新线程,总共创建10个线程。超过此限制后,线程将按预期重用。因为新的工作线程是在前一个工作线程完成后按顺序创建的,我不明白为什么第一个线程没有立即重用,因为前一个工作线程已经完成了它的工作。假设只有一个线程,它同时执行一些工作。我希望线程池只创建一个线程,这足以服务于所有任务。这是正常的行为吗?或者可能有什么问题,什么会拒绝第一个线程的可重用性,并迫使线程池创建另一个线程
如果这是正常的,我认为创建不需要的线程和保持线程就绪的内存是浪费时间。我能设法避免吗?我能强迫SwingWorker的池中只有一个线程吗我认为不会,因为据我所知,线程的数量是恒定的,并且依赖于Java实现
我可以让SwingWorker在任务完成后完成线程吗?(在done()方法中调用this.cancel()无效)
下面是我的真实世界工作者的代码,以防存在可能导致问题的依赖关系
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()方法中,创建了一个带有阻塞调用的新线程,并返回了线程id,这应该不会有什么奇怪的地方。别问我为什么,这不是我的代码。:)
# 1 楼答案
嗯。。。SwingWorkers的默认ThreadPoolExecutor不仅配置为最大池大小为10,还配置为核心大小为10,这意味着它更喜欢保持10个线程处于活动状态。我很难说为什么会这样,也许在某些条件下它是最优的
您可以使用以下(奇怪的)调用告诉SwingWorkers使用自定义ExecutorService:
注意,Executor返回的Executor服务。newSingleThreadExecutor()将创建一个非守护进程线程,这是您可能需要更改的