Swing 线程之SwingUtilities.invokeLater()
2013-09-30 15:48
274 查看
现在我们要做一个简单的界面。
包括一个进度条、一个输入框、开始和停止按钮。
需要实现的功能是:
当点击开始按钮,则更新进度条,并且在输入框内把完成的百分比输出(这里只做例子,没有真正去做某个工作)。
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.FlowLayout;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionEvent;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionListener;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JButton;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JFrame;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JProgressBar;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JTextField;
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class SwingThreadTest1 extends JFrame {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final long serialVersionUID = 1L;
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final String STR = "Completed : ";
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JProgressBar progressBar = new JProgressBar();
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JTextField text = new JTextField(10);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton start = new JButton("Start");
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton end = new JButton("End");
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private boolean flag = false;
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private int count = 0;
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public SwingThreadTest1() {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
this.setLayout(new FlowLayout());
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(progressBar);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setEditable(false);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(text);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(start);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(end);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
start.addActionListener(new Start());
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
end.addActionListener(new End());
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void go() {
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while (count < 100) {
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
try {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
Thread.sleep(100);//这里比作要完成的某个耗时的工作
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
} catch (InterruptedException e) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
e.printStackTrace();
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
//更新进度条和输入框
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (flag) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
count++;
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
progressBar.setValue(count);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setText(STR + String.valueOf(count) + "%");
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class Start implements ActionListener {
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = true;//设置开始更新的标志
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
go();//开始工作
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class End implements ActionListener {
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = false;//停止
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static void main(String[] args) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
SwingThreadTest1 fg = new SwingThreadTest1();
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setSize(300, 100);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setVisible(true);
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
运行代码发现,
现象1:当点击了开始按钮,画面就卡住了。按钮不能点击,进度条没有被更新,输入框上也没有任何信息。
原因分析:Swing是线程不安全的,是单线程的设计,所以只能从事件派发线程访问将要在屏幕上绘制的Swing组件。ActionListener的actionPerformed方法是在事件派发线程中调用执行的,而点击了开始按钮后,执行了go()方法,在go()里,虽然也去执行了更新组件的方法
progressBar.setValue(count);
text.setText(STR + String.valueOf(count) + "%");
但由于go()方法直到循环结束,它并没有返回,所以更新组件的操作一直没有被执行,这就造成了画面卡住的现象。
现象2:过了一段时间(go方法里的循环结束了)后,画面又可以操作,并且进度条被更新,输入框也出现了我们想看到的信息。
原因分析:通过在现象1的分析,很容易联想到,当go()方法返回了,则其他的线程(更新组件)可以被派发了,所以画面上的组件被更新了。
为了让画面不会卡住,我们来修改代码,将耗时的工作放在一个线程里去做。
代码2:
1
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.FlowLayout;
2
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionEvent;
3
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionListener;
4
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JButton;
5
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JFrame;
6
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JProgressBar;
7
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JTextField;
8
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class SwingThreadTest2 extends JFrame {
9
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final long serialVersionUID = 1L;
10
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final String STR = "Completed : ";
11
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JProgressBar progressBar = new JProgressBar();
12
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JTextField text = new JTextField(10);
13
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton start = new JButton("Start");
14
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton end = new JButton("End");
15
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private boolean flag = false;
16
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private int count = 0;
17
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
18
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
GoThread t = null;
19
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public SwingThreadTest2() {
20
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
this.setLayout(new FlowLayout());
21
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(progressBar);
22
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setEditable(false);
23
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(text);
24
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(start);
25
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(end);
26
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
start.addActionListener(new Start());
27
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
end.addActionListener(new End());
28
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
29
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void go() {
30
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while (count < 100) {
31
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
try {
32
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
Thread.sleep(100);
33
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
} catch (InterruptedException e) {
34
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
e.printStackTrace();
35
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
36
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (flag) {
37
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
count++;
38
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
System.out.println(count);
39
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
progressBar.setValue(count);
40
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setText(STR + String.valueOf(count) + "%");
41
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
42
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
43
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
44
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class Start implements ActionListener {
45
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
46
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = true;
47
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if(t == null){
48
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
t = new GoThread();
49
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
t.start();
50
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
51
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
52
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
53
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
//执行复杂工作,然后更新组件的线程
54
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
class GoThread extends Thread{
55
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void run() {
56
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
//do something
![](http://www.blogjava.net/Images/dot.gif)
57
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
go();
58
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
59
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
60
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class End implements ActionListener {
61
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
62
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = false;
63
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
64
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
65
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static void main(String[] args) {
66
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
SwingThreadTest2 fg = new SwingThreadTest2();
67
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
68
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setSize(300, 100);
69
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setVisible(true);
70
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
71
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
我们执行了程序,结果和我们想要的一样,画面不会卡住了。
那这个程序是否没有问题了呢?
我们自定义了一个线程GoThread,在这里我们完成了那些耗时的工作,可以看作是“工作线程”,
而对于组件的更新,我们也放在了“工作线程”里完成了。
在这里,在事件派发线程以外的线程里设置进度条,是一个危险的操作,运行是不正常的。(对于输入框组件的更新是安全的。)
只有从事件派发线程才能更新组件,根据这个原则,我们来修改我们现有代码。
1
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.FlowLayout;
2
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionEvent;
3
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionListener;
4
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JButton;
5
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JFrame;
6
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JProgressBar;
7
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JTextField;
8
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.SwingUtilities;
9
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class SwingThreadTest3 extends JFrame {
10
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final long serialVersionUID = 1L;
11
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final String STR = "Completed : ";
12
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JProgressBar progressBar = new JProgressBar();
13
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JTextField text = new JTextField(10);
14
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton start = new JButton("Start");
15
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton end = new JButton("End");
16
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private boolean flag = false;
17
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private int count = 0;
18
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
19
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private GoThread t = null;
20
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
21
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private Runnable run = null;//更新组件的线程
22
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public SwingThreadTest3() {
23
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
this.setLayout(new FlowLayout());
24
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(progressBar);
25
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setEditable(false);
26
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(text);
27
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(start);
28
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(end);
29
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
start.addActionListener(new Start());
30
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
end.addActionListener(new End());
31
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
32
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
run = new Runnable(){//实例化更新组件的线程
33
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void run() {
34
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
progressBar.setValue(count);
35
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setText(STR + String.valueOf(count) + "%");
36
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
37
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
};
38
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
39
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void go() {
40
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while (count < 100) {
41
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
try {
42
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
Thread.sleep(100);
43
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
} catch (InterruptedException e) {
44
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
e.printStackTrace();
45
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
46
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (flag) {
47
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
count++;
48
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
SwingUtilities.invokeLater(run);//将对象排到事件派发线程的队列中
49
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
50
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
51
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
52
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class Start implements ActionListener {
53
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
54
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = true;
55
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if(t == null){
56
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
t = new GoThread();
57
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
t.start();
58
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
59
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
60
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
61
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
62
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
class GoThread extends Thread{
63
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void run() {
64
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
//do something
![](http://www.blogjava.net/Images/dot.gif)
65
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
go();
66
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
67
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
68
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class End implements ActionListener {
69
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
70
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = false;
71
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
72
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
73
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static void main(String[] args) {
74
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
SwingThreadTest3 fg = new SwingThreadTest3();
75
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
76
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setSize(300, 100);
77
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setVisible(true);
78
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
79
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
解释:SwingUtilities.invokeLater()方法使事件派发线程上的可运行对象排队。当可运行对象排在事件派发队列的队首时,就调用其run方法。其效果是允许事件派发线程调用另一个线程中的任意一个代码块。
还有一个方法SwingUtilities.invokeAndWait()方法,它也可以使事件派发线程上的可运行对象排队。
他们的不同之处在于:SwingUtilities.invokeLater()在把可运行的对象放入队列后就返回,而SwingUtilities.invokeAndWait()一直等待知道已启动了可运行的run方法才返回。如果一个操作在另外一个操作执行之前必须从一个组件获得信息,则应使用SwingUtilities.invokeAndWait()方法。
包括一个进度条、一个输入框、开始和停止按钮。
需要实现的功能是:
当点击开始按钮,则更新进度条,并且在输入框内把完成的百分比输出(这里只做例子,没有真正去做某个工作)。
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.FlowLayout;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionEvent;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionListener;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JButton;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JFrame;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JProgressBar;
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JTextField;
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class SwingThreadTest1 extends JFrame {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final long serialVersionUID = 1L;
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final String STR = "Completed : ";
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JProgressBar progressBar = new JProgressBar();
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JTextField text = new JTextField(10);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton start = new JButton("Start");
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton end = new JButton("End");
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private boolean flag = false;
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private int count = 0;
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public SwingThreadTest1() {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
this.setLayout(new FlowLayout());
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(progressBar);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setEditable(false);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(text);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(start);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(end);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
start.addActionListener(new Start());
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
end.addActionListener(new End());
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void go() {
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while (count < 100) {
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
try {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
Thread.sleep(100);//这里比作要完成的某个耗时的工作
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
} catch (InterruptedException e) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
e.printStackTrace();
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
//更新进度条和输入框
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (flag) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
count++;
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
progressBar.setValue(count);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setText(STR + String.valueOf(count) + "%");
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class Start implements ActionListener {
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = true;//设置开始更新的标志
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
go();//开始工作
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class End implements ActionListener {
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = false;//停止
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static void main(String[] args) {
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
SwingThreadTest1 fg = new SwingThreadTest1();
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setSize(300, 100);
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setVisible(true);
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
运行代码发现,
现象1:当点击了开始按钮,画面就卡住了。按钮不能点击,进度条没有被更新,输入框上也没有任何信息。
原因分析:Swing是线程不安全的,是单线程的设计,所以只能从事件派发线程访问将要在屏幕上绘制的Swing组件。ActionListener的actionPerformed方法是在事件派发线程中调用执行的,而点击了开始按钮后,执行了go()方法,在go()里,虽然也去执行了更新组件的方法
progressBar.setValue(count);
text.setText(STR + String.valueOf(count) + "%");
但由于go()方法直到循环结束,它并没有返回,所以更新组件的操作一直没有被执行,这就造成了画面卡住的现象。
现象2:过了一段时间(go方法里的循环结束了)后,画面又可以操作,并且进度条被更新,输入框也出现了我们想看到的信息。
原因分析:通过在现象1的分析,很容易联想到,当go()方法返回了,则其他的线程(更新组件)可以被派发了,所以画面上的组件被更新了。
为了让画面不会卡住,我们来修改代码,将耗时的工作放在一个线程里去做。
代码2:
1
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.FlowLayout;
2
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionEvent;
3
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionListener;
4
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JButton;
5
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JFrame;
6
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JProgressBar;
7
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JTextField;
8
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class SwingThreadTest2 extends JFrame {
9
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final long serialVersionUID = 1L;
10
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final String STR = "Completed : ";
11
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JProgressBar progressBar = new JProgressBar();
12
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JTextField text = new JTextField(10);
13
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton start = new JButton("Start");
14
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton end = new JButton("End");
15
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private boolean flag = false;
16
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private int count = 0;
17
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
18
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
GoThread t = null;
19
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public SwingThreadTest2() {
20
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
this.setLayout(new FlowLayout());
21
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(progressBar);
22
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setEditable(false);
23
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(text);
24
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(start);
25
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(end);
26
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
start.addActionListener(new Start());
27
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
end.addActionListener(new End());
28
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
29
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void go() {
30
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while (count < 100) {
31
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
try {
32
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
Thread.sleep(100);
33
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
} catch (InterruptedException e) {
34
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
e.printStackTrace();
35
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
36
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (flag) {
37
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
count++;
38
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
System.out.println(count);
39
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
progressBar.setValue(count);
40
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setText(STR + String.valueOf(count) + "%");
41
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
42
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
43
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
44
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class Start implements ActionListener {
45
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
46
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = true;
47
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if(t == null){
48
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
t = new GoThread();
49
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
t.start();
50
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
51
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
52
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
53
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
//执行复杂工作,然后更新组件的线程
54
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
class GoThread extends Thread{
55
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void run() {
56
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
//do something
![](http://www.blogjava.net/Images/dot.gif)
57
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
go();
58
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
59
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
60
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class End implements ActionListener {
61
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
62
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = false;
63
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
64
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
65
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static void main(String[] args) {
66
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
SwingThreadTest2 fg = new SwingThreadTest2();
67
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
68
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setSize(300, 100);
69
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setVisible(true);
70
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
71
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
我们执行了程序,结果和我们想要的一样,画面不会卡住了。
那这个程序是否没有问题了呢?
我们自定义了一个线程GoThread,在这里我们完成了那些耗时的工作,可以看作是“工作线程”,
而对于组件的更新,我们也放在了“工作线程”里完成了。
在这里,在事件派发线程以外的线程里设置进度条,是一个危险的操作,运行是不正常的。(对于输入框组件的更新是安全的。)
只有从事件派发线程才能更新组件,根据这个原则,我们来修改我们现有代码。
1
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.FlowLayout;
2
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionEvent;
3
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import java.awt.event.ActionListener;
4
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JButton;
5
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JFrame;
6
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JProgressBar;
7
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.JTextField;
8
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
import javax.swing.SwingUtilities;
9
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif)
public class SwingThreadTest3 extends JFrame {
10
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final long serialVersionUID = 1L;
11
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private static final String STR = "Completed : ";
12
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JProgressBar progressBar = new JProgressBar();
13
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JTextField text = new JTextField(10);
14
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton start = new JButton("Start");
15
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private JButton end = new JButton("End");
16
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private boolean flag = false;
17
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private int count = 0;
18
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
19
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private GoThread t = null;
20
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
21
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
private Runnable run = null;//更新组件的线程
22
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public SwingThreadTest3() {
23
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
this.setLayout(new FlowLayout());
24
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(progressBar);
25
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setEditable(false);
26
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(text);
27
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(start);
28
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
add(end);
29
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
start.addActionListener(new Start());
30
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
end.addActionListener(new End());
31
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
32
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
run = new Runnable(){//实例化更新组件的线程
33
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void run() {
34
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
progressBar.setValue(count);
35
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
text.setText(STR + String.valueOf(count) + "%");
36
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
37
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
};
38
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
39
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private void go() {
40
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
while (count < 100) {
41
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
try {
42
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
Thread.sleep(100);
43
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
} catch (InterruptedException e) {
44
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
e.printStackTrace();
45
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
46
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (flag) {
47
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
count++;
48
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
SwingUtilities.invokeLater(run);//将对象排到事件派发线程的队列中
49
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
50
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
51
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
52
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class Start implements ActionListener {
53
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
54
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = true;
55
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if(t == null){
56
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
t = new GoThread();
57
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
t.start();
58
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
59
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
60
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
61
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
62
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
class GoThread extends Thread{
63
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void run() {
64
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
//do something
![](http://www.blogjava.net/Images/dot.gif)
65
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
go();
66
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
67
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
68
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
private class End implements ActionListener {
69
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public void actionPerformed(ActionEvent e) {
70
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
flag = false;
71
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
72
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
73
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static void main(String[] args) {
74
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
SwingThreadTest3 fg = new SwingThreadTest3();
75
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
76
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setSize(300, 100);
77
![](http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif)
fg.setVisible(true);
78
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
}
79
![](http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif)
}
解释:SwingUtilities.invokeLater()方法使事件派发线程上的可运行对象排队。当可运行对象排在事件派发队列的队首时,就调用其run方法。其效果是允许事件派发线程调用另一个线程中的任意一个代码块。
还有一个方法SwingUtilities.invokeAndWait()方法,它也可以使事件派发线程上的可运行对象排队。
他们的不同之处在于:SwingUtilities.invokeLater()在把可运行的对象放入队列后就返回,而SwingUtilities.invokeAndWait()一直等待知道已启动了可运行的run方法才返回。如果一个操作在另外一个操作执行之前必须从一个组件获得信息,则应使用SwingUtilities.invokeAndWait()方法。
相关文章推荐
- Swing 线程之SwingUtilities.invokeLater()
- 【Java线程】Swing事件分发线程EDT与SwingUtilities.invokeLater
- Swing 线程之SwingUtilities.invokeLater()
- Swing 线程之SwingUtilities.invokeLater()
- Swing 线程之SwingUtilities.invokeLater()
- Swing 线程之SwingUtilities.invokeLater()
- Swing事件分发线程EDT与SwingUtilities.invokeLater
- Swing事件分发线程EDT与SwingUtilities.invokeLater
- Swing 线程之SwingUtilities.invokeLater()(转帖)---Swing是线程不安全的,是单线程的设计
- Swing 线程之SwingUtilities.invokeLater()
- Swing事件分发线程EDT与SwingUtilities.invokeLater
- Swing 线程之SwingUtilities.invokeLater()
- Swing 线程之SwingUtilities.invokeLater()
- Swing 线程之SwingUtilities.invokeLater()
- Swing 线程之SwingUtilities.invokeLater()
- Java中事件分发线程(EDT)与SwingUtilities.invokeLater相关总结
- Swing 线程之 SwingUtilities.invokeLater()
- 调用SwingUtilities.invokeLater()将更新UI的操作放到事件派发线程中执行
- Java-Swing: SwingUtilities中invokeLater和invokeAndWait介绍
- Java GUI编程SwingUtilities.invokeLater作用