Java 中的 Swing 是线程安全的吗?
awtjavaobject oriented programmingprogrammingswing
不,Java Swing 组件在 Java 中不是线程安全的。
为什么 Swing 组件不是线程安全的
- Java Swing 不是线程安全的其中一个主要原因是简化了扩展其组件的任务。
- Java Swing 不是线程安全的另一个原因是,获取和释放锁以及恢复状态会产生开销。
- 某些 Java Swing 组件方法将支持多线程访问,例如 JComponent 类的 repaint()、revalidate() 和 invalidate() 方法。
事件派发线程(EDT)
只有当组件可用于在屏幕上绘制时,才可以从事件分派线程 (EDT) 访问 Java Swing 组件。EDT线程是调用回调方法(例如 paint() 和 update())以及在 事件侦听器接口中定义的事件处理程序方法的线程。只有线程安全方法才能从任何线程安全地调用。由于大多数 Swing 对象方法都不是线程安全的,因此可以从单个线程(即 EDT)调用它们。
示例
import javax.swing.*; import java.awt.Dimension; import java.awt.event.*; public class EDTTest extends JPanel implements ActionListener { private static EDTTest myPanel; private static JFrame myFrame; public EDTTest() { super(); } public Dimension getPreferredSize() { return new Dimension(500,425); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } private static void createAndShowGUI() { myFrame = new JFrame("EDT Program"); myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); myFrame.setLocationRelativeTo(null); myPanel = new EDTTest(); myFrame.add(myPanel); initMenu(); myFrame.setVisible(true); } private static void initMenu() { JMenuBar menuBar = new JMenuBar(); myFrame.setJMenuBar(menuBar); JMenu file = new JMenu("File"); JMenuItem quit = new JMenuItem("Quit"); quit.addActionListener(myPanel); file.add(quit); menuBar.add(file); } public void actionPerformed(ActionEvent ae) { String choice = ae.getActionCommand(); if (choice.equals("Quit")) { System.exit(0); } } }
在上面的例子中,SwingUtilities.invokeLater()方法将延迟 GUI 创建任务,直到初始线程的任务完成后才确保 GUI 创建在 EDT 内进行。