gpt4 book ai didi

java - SwingWorker 线程可重用性

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:51:04 25 4
gpt4 key购买 nike

我想知道当重复执行某些任务时,java SwingWorker 及其线程池如何工作。这是准备复制粘贴的问题的 SSCCE:

    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 个线程。超过这个限制后,线程如我所料被重用。因为新的 worker 是在前一个 worker 完成后按顺序创建的,我不明白,为什么第一个线程没有立即重用,因为前一个 worker 已经完成了它的工作。假设只能有一个线程,它同时做一些工作。我希望线程池只创建一个线程,足以为所有任务提供服务。这是通常的行为吗?或者可能有什么问题拒绝第一个线程的可重用性并强制线程池创建另一个线程?

如果这是正常的,我认为创建不需要的线程和内存来保持线程就绪是浪费时间。我能以某种方式避免它吗?我可以强制 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,这应该没什么奇怪的。不要问我为什么,这不是我的代码。 :)

最佳答案

嗯……SwingWorkers 的默认 ThreadPoolExecutor 配置为不仅最大池大小为 10,而且核心大小也为 10,这意味着它更愿意保持 10 个线程处于 Activity 状态。我很难说出这是为什么,也许它在某些条件下是最佳的。

您可以使用这个(奇怪的)调用告诉 SwingWorkers 使用自定义 ExecutorService:

AppContext.getAppContext().put( SwingWorker.class, Executors.newSingleThreadExecutor() );

请注意,Executors.newSingleThreadExecutor() 返回的 ExecutorService 将创建一个非守护线程,您可能需要更改此内容。

关于java - SwingWorker 线程可重用性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18659709/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com