Java Swing 是线程安全的吗?


不,**Java Swing** 组件在 Java 中不是线程安全的。

为什么 Swing 组件不是线程安全的

  • Java Swing 不是线程安全的主要原因之一是为了简化扩展其组件的任务。
  • Java Swing 不是线程安全的另一个原因是获取和释放锁以及恢复状态所涉及的开销。
  • 一些 Java Swing 组件方法支持多线程访问,例如 **JComponent** 类的 **repaint()、revalidate()** 和 **invalidate() 方法**。

事件分发线程 (EDT)

一旦组件可用于屏幕上绘制,Java Swing 组件只能从 **事件分发线程 (EDT)** 访问。**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 中。

输出

更新于:2020年2月7日

1K+ 次浏览

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告