【发布时间】:2014-11-09 22:30:08
【问题描述】:
我正在阅读 Thinking in Java,作者强调 main 方法不应该调用 swing 方法。作为该实践的一个示例,他提供了以下代码(可在他的网页上找到):
//: gui/SubmitSwingProgram.java
import javax.swing.*;
import java.util.concurrent.*;
public class SubmitSwingProgram extends JFrame {
JLabel label;
public SubmitSwingProgram() {
super("Hello Swing");
label = new JLabel("A Label");
add(label);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 100);
setVisible(true);
}
static SubmitSwingProgram ssp;
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() { ssp = new SubmitSwingProgram(); }
});
TimeUnit.SECONDS.sleep(1);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ssp.label.setText("Hey! This is Different!");
}
});
}
} ///:~
然后通过invokeLater 方法创建并初始化gui 对象,使其成为线程安全的。但几页后作者提供了以下代码:
//: gui/Button2.java
// Responding to button presses.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import static net.mindview.util.SwingConsole.*;
public class Button2 extends JFrame {
private JButton
b1 = new JButton("Button 1"),
b2 = new JButton("Button 2");
private JTextField txt = new JTextField(10);
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String name = ((JButton)e.getSource()).getText();
txt.setText(name);
}
}
private ButtonListener bl = new ButtonListener();
public Button2() {
b1.addActionListener(bl);
b2.addActionListener(bl);
setLayout(new FlowLayout());
add(b1);
add(b2);
add(txt);
}
public static void main(String[] args) {
run(new Button2(), 200, 150);
}
} ///:~
SwingConsole 在哪里:
//: net/mindview/util/SwingConsole.java
// Tool for running Swing demos from the
// console, both applets and JFrames.
package net.mindview.util;
import javax.swing.*;
public class SwingConsole {
public static void
run(final JFrame f, final int width, final int height) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f.setTitle(f.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(width, height);
f.setVisible(true);
}
});
}
} ///:~
因此与前面的示例相反,在主方法/主线程中创建并初始化了一个实现 JFrame 的对象。
我的问题是: (1) 第二个例子是错的还是第一个被夸大了? (2) 仅在 setVisible 调用之后和该语句之前通过invokeLater 调用swing 方法就足够了,在主线程中调用swing 方法是安全的吗?
【问题讨论】:
-
他可能会争辩说,在框架被打包或可见(也就是实现)之前,它可以安全处理。这种想法的问题是,您只是不知道什么会触发事件队列的请求。在 EDT 的上下文中初始化 UI 总是更安全
标签: java multithreading swing thread-safety event-dispatch-thread