Swing EDT

Swing 的线程策略

总结一句话:对Swing所有组件和model(模型)的更改 必须至于EDT 事件派发线程中.

 

通常 Swing 不是线程安全的。除非另行说明,否则所有 Swing 组件及相关类都必须在事件调度线程上访问。

典型的 Swing 应用程序执行处理以响应用户动作所生成的事件。例如,单击 JButton 通知所有添加到 JButtonActionListener。由于用户动作所生成的所有事件都在调度线程上指派,所以大部分开发人员不受该限制的影响。

但是,影响存在于构造以及显示 Swing 的应用程序中。对应用程序的 main 方法或 Applet 中方法的调用不在事件调度线程上调用。因此,构造和显示应用程序或 applet 时,必须注意要将控件转移到事件调度线程。转移控件和开始处理 Swing 的首选方法是使用 invokeLaterinvokeLater 方法安排 Runnable 在事件调度线程上处理。以下两个示例都同样很好地用于转移控件和启动 Swing 应用程序:

public class MyApp implements Runnable {
    public void run() {
        // Invoked on the event dispatching thread.
        // Construct and show GUI.
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new MyApp(args));
    }
}

或:

public class MyApp {
    MyApp(String[] args) {
        // Invoked on the event dispatching thread. Do any initialization
        // here.
    }

    public void show() {
        // Show the UI.
    }

    public static void main(final String[] args) {
        // Schedule a job for the event-dispatching thread:
        // creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new MyApp(args).show();
            }
        });
    }
}

此限制也适用于连接到 Swing 组件的模型。例如,如果将 TableModel 连接到 JTable,则 TableModel 应该只在事件调度线程上进行修改。如果修改单独线程上的模型,就有遭遇异常和可能的显示损坏的风险。

由于所有事件都是在事件调度线程上传递的,所以必须注意事件处理。尤其是,在事件调度线程上执行的长运行时间任务(如网络 io 或计算密集处理)将阻塞事件调度线程调度任何其他线程。事件调度线程受阻塞时,应用程序对用户输入完全没有反应。有关处理 Swing 时执行这种处理的首选方式,请参阅 SwingWorker

你可能感兴趣的:(SWING EDT)