在Java的Swing中,任何一个关于GUI的任务都是用EDT线程(Event Dispatching Thread)完成的,其主要使用的是多个生产者,一个消费者的模式设计的。
上述的设计方案的好处是降低消费者EDT线程的复杂性
坏处也显而易见,一旦开发人员编程不当,使用EDT线程去做耗时的任务时,GUI可能就无响应。
解决上述问题的办法是,使用Thread-Per-Message Thread Pattern,当一个组件事件发生时,产生一个线程去处理这个任务。
如果涉及到了组件的修改,比如修改Label标签时,可以使用Javax.swing.SwingUtilities.*中的异步执行方法invokeLater(Runnable)或者同步执行方法invokeAndWait(Runnable);
比如:
private final JLabel label=new JLabel();
invokeLater(new Runnable(){
public void run(){
label.setName("Cao Ning is talent");
}
});
解决停止任务的方法是,采用Two-Phase Termination Pattern
使用一个标志位,和interrupt()方法。
具体的一个例子如下:
public class Main {
public static void main(String[] args) {
new MyFrame();
}
}
package Q10_5;
import java.io.IOException;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
public class MyFrame extends JFrame implements ActionListener {
private final JButton executeButton = new JButton("Execute");
private final JButton cancelButton = new JButton("Cancel");
public MyFrame() {
super("MyFrame");
getContentPane().setLayout(new FlowLayout());
getContentPane().add(new JLabel("Two-Phase Termination Sample"));
getContentPane().add(executeButton);
getContentPane().add(cancelButton);
executeButton.addActionListener(this);
cancelButton.addActionListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == executeButton) {
// 开始执行服务
Service.service();
} else if (e.getSource() == cancelButton) {
// 终止服务
Service.cancel();
}
}
}
package Q10_5;
public class Service {
private static Thread thread=null;
private volatile static boolean stop=false;
// 开始执行服务
public synchronized static void service() {
if(thread!=null) {
System.out.print("balking");
return; //balking
}
thread=new Thread() {
public void run() {
System.out.print("service");
try {
for (int i = 0; i < 50 && stop == false; i++) {
System.out.print(".");
Thread.sleep(100);
}
} catch (InterruptedException e) {
System.out.print("interrupted.");
}
thread=null;
stop=false;
System.out.println("done.");
}
};
thread.start();
}
//终止服务
public static void cancel() {
if(thread!=null){
stop=true;
thread.interrupt();
}
}
}