即使使用SwingWorker,Java GUI也会冻结
我正在尝试使用SwingWorker执行一项冗长的任务,并使用以下结果更新JLabel:即使使用SwingWorker,Java GUI也会冻结,java,multithreading,swing,swingworker,Java,Multithreading,Swing,Swingworker,我正在尝试使用SwingWorker执行一项冗长的任务,并使用以下结果更新JLabel: button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { new SwingWorker<String, Void>() { @Override protect
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<String, Void>() {
@Override
protected String doInBackground() throws Exception {
return doCalculation();
}
protected void done() {
try {
label.setText(get());
} catch (InterruptedException e) {
System.out.println("thread was interrupted");
} catch (ExecutionException e) {
System.out.println("there was an ExecutionException");
}
}
}.execute();
}
});
button.addActionListener(新ActionListener(){
@凌驾
已执行的公共无效操作(操作事件arg0){
新SwingWorker(){
@凌驾
受保护的字符串doInBackground()引发异常{
返回doccalculation();
}
受保护的void done(){
试一试{
label.setText(get());
}捕捉(中断异常e){
System.out.println(“线程被中断”);
}捕获(执行例外){
System.out.println(“存在执行异常”);
}
}
}.execute();
}
});
我可以随意多次单击该按钮,Gui将保持响应,直到两个线程完成,此时Gui在线程运行时冻结。如果我一次只运行一个线程,这个问题仍然会发生
如果有人能指出我是否错误地使用了SwingWorker,或者是否有其他我不知道的问题,我将不胜感激。谢谢你抽出时间。
伊恩
编辑
doCalculation()只是一个耗时的过程:
private String doCalculation() {
for (int i = 0; i < 10000000; i++) {
Math.pow(3.14, i);
}
return threads++ + "";
}
private String doccalculation(){
对于(int i=0;i<10000000;i++){
数学.pow(3.14,i);
}
返回线程+++;
}
很抱歉,即使使用doCalculate()方法,我仍然无法重现您的问题。例如,下面是我的:
导入java.awt.event.*;
导入java.util.concurrent.ExecutionException;
导入javax.swing.*;
公共类FooGui{
私有静态int线程=0;
私有静态void createAndShowUI(){
最终JLabel标签=新JLabel(“”);
JButton按钮=新JButton(“按钮”);
addActionListener(新建ActionListener()){
@凌驾
已执行的公共无效操作(操作事件arg0){
新SwingWorker(){
@凌驾
受保护的字符串doInBackground()引发异常{
返回doccalculation();
}
@凌驾
受保护的void done(){
试一试{
label.setText(get());
}捕捉(中断异常e){
System.out.println(“线程被中断”);
}捕获(执行例外){
System.out.println(“存在执行异常”);
}
}
}.execute();
}
});
JPanel面板=新的JPanel();
面板。添加(按钮);
面板。添加(标签);
JFrame=newjframe(“FooGui”);
frame.getContentPane().add(面板);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
}
私有静态字符串doCalculation(){
对于(int i=0;i<5000000;i++){
数学.pow(3.14,i);
}
返回线程+++;
}
公共静态void main(字符串[]args){
invokeLater(new Runnable()){
@凌驾
公开募捐{
createAndShowUI();
}
});
}
}
您可能希望创建并发布您自己的(请检查链接)。我敢打赌,在创建这个过程中,您可能会自己找到问题及其解决方案。如果是这样,请务必回到这里,让我们知道
我知道这不是一个真正的答案,但是没有办法在评论中发布这样的代码 到目前为止,我没有看到您发布的代码有任何明显的错误,但我认为这里的关键是
doccalculation()中发生的事情代码>方法。你能发这个代码吗?谢谢你的帮助,我很感激。我在你的例子中也发现了同样的冻结,所以我尝试了一下。从eclipse/命令行运行可以复制这一点。我创建了一个可运行的jar,它运行得非常好。我正在运行64位Windows7。我在Ubuntu上试过,似乎也解决了这个问题。再次感谢。我从来没有看到过那个内在的监听器,我不确定放…,但你的帖子,这可能是可行的方式,很好的例子,没有性能问题+1@Ian:嗯,如果能知道为什么在某些情况下会发生冰冻,那就太好了。也许这与线程太多有关。我听说在处理多个线程时,有时不能使用SwingWorker,而需要使用ExecutorService和线程池。我的应用程序也有类似的问题,通过IDE运行它也是我的问题。
import java.awt.event.*;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
public class FooGui {
private static int threads = 0;
private static void createAndShowUI() {
final JLabel label = new JLabel(" ");
JButton button = new JButton("Button");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<String, Void>() {
@Override
protected String doInBackground() throws Exception {
return doCalculation();
}
@Override
protected void done() {
try {
label.setText(get());
} catch (InterruptedException e) {
System.out.println("thread was interrupted");
} catch (ExecutionException e) {
System.out.println("there was an ExecutionException");
}
}
}.execute();
}
});
JPanel panel = new JPanel();
panel.add(button);
panel.add(label);
JFrame frame = new JFrame("FooGui");
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static String doCalculation() {
for (int i = 0; i < 5000000; i++) {
Math.pow(3.14, i);
}
return threads++ + "";
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowUI();
}
});
}
}