测试代码如下:
1、耗时计算没有单独起线程处理,耗时计算在EDT线程执行,导致界面没有响应,处于卡死状态
package thread;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
JFrame frame=new JFrame();
final JButton button=new JButton();
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
button.setLabel("busy");
button.setEnabled(false);
//ExecutorService executorService=Executors.newCachedThreadPool();
//executorService.execute(new Runnable() {
//
//public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10000000; i++) {
System.out.println("operation is running");
}
//button.setLabel("");
//}
//});
}
});
button.setSize(50, 20);
frame.add(button);
frame.setVisible(true);
frame.pack();
}
}
2、
2、起线程处理耗时操作,耗时操作单独在一个线程处理,界面及时响应,没有问题
3、窗体设置部分代码在主线程处理
4、建议代码如下,对界面的操作应该放在edt线程里去处理,即使是组件的初始化也最好放在EDT中处理,虽然从主线成直接初始化组件发生的错误概率很小,但还是要避免。
上述的SwingUtilites.invokeLater也可有EventQueue.invokeLater代替,这两个方法都是正确的,选择任何一个都可以。实际上,SwingUtilities版只是一个薄薄的封装方法,它直接调用 EventQueue.invokeLater。因为Swing框架本身经常调用SwingUtilities,使用SwingUtilities可以减 少程序引入的类。
第一条规则同通常称为单一线程规则,在任何非EDT线程中都不该接触swing组件。这两条规则看似是矛盾的,既然将耗时的操作放入其他其他线程,那么当耗时操作完成时如何将结果更新到swing组件当中去?因为不能在其他线程中接触swing组件的。其实想想也不难,既然EDT本质上是从事件队列中拿出事件来处理的,那么只要能在其他线程中把耗时操作完成以后再把更细ui组件的代码封装放到事件队列中就行了,到时EDT自然会从事件队列取出代码执行用以达到更新的目的,这样两条规则都满足了。其实在任何线程中,可以使用两种方法想事件队列添加任意的动作。即调用SwingUtilites类(或者EventQueue类也是一样)invokeLater或者invokeAndWait两个静态方法向事件队列添加任务。
package thread;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
JFrame frame=new JFrame();
final JButton button=new JButton();
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
button.setLabel("busy");
button.setEnabled(false);
ExecutorService executorService=Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10000000; i++) {
System.out.println("operation is running");
}
//对gui组建的操作放在edt线程处理
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// TODO Auto-generated method stub
button.setLabel("");
}
});
}
});
}
});
//界面的初始化其实也不应该放在主线程执行,应该放在edt线程,虽然出错的概率不大
button.setSize(50, 20);
frame.add(button);
frame.setVisible(true);
frame.pack();
}
}