Swing中的JFrame窗口是在自己独立的线程上运行的吗?

时间:2016-08-26 01:14:56

标签: java swing jvm event-dispatch-thread

我有三个问题密切相关,因为它们彼此诞生并代表了一系列思路,所以我将它们发布在一个问题之下。如果我单独发布它,那对我构建我的问题的大图片无济于事。

1)你能用简单的语言解释SwingUtilities.invokeLater的作用吗?我理解线程,我敢说了很多,但文档的语言仍然让我感到困惑。它说:

  

导致 doRun.run()异步执行   AWT事件调度线程。毕竟这会发生   待处理的AWT事件已经处理完毕。这个方法应该   在应用程序线程需要更新GUI时使用。   在以下示例中,invokeLater呼叫队列   Runnable对象doHelloWorld   在事件调度线程和   然后打印一条消息。

如果我付出一些努力来理解所说的内容,我认为这就是它所说的,但我不能确定它。我想它说:

invokeLater方法仅在应用程序的主线程上调度主窗口创建和调度程序/消息泵的设置,而不是在单独的线程上。它通过发布消息来创建窗口并在主/主应用程序线程上进行设置。换句话说,主要话题是对我们说,"你要我创建的窗口将在我完成其他现在的工作之后创建。"

但是有两件事让我感到困惑,我将其列为下面的两个问题。

2)那么为什么我需要将新窗口的消息循环实现为Runnable。这意味着我想要一个单独的线程来执行该消息循环。

3)我在创建窗口的函数和窗口的消息循环函数中打印出当前线程ID,它们都是不同的线程。那么,Swing中的每个窗口都在自己的线程上运行?那太疯狂了。你能告诉我这里发生了什么吗?如果你能在一段或两段中解释在Swing中创建的GUI应用程序的线程模型?

public static void main(String[] args) {
        SwingUtilities.invokeLater(new MainWindowEventLoop());
        System.out.println(String.format("Main thread %1$d started.",
                            Thread.currentThread().getId()));
    }

public class MainWindowEventLoop implements Runnable {

    @Override
    public void run() {
        JFrame mainWindow = new MainWindow("Main Window");
        System.out.println(String.format("Main window loop running on thread %1$d.", 
                            Thread.currentThread().getId()));
    }
}
  

输出:

     

主线程1已启动。

     

主要窗口循环在线程14上运行。

2 个答案:

答案 0 :(得分:6)

这有点复杂,但Swing不是线程安全的。为了以异步和安全的方式运行GUI,Sun / Oracle使用称为Ad-Hoc Thread Confinement的锁定模式。所有Swing组件必须在AWT EDT(事件调度线程)上运行,否则结果不是线程安全的。

这是Oracle教程的链接。尝试阅读所有这些部分,看看它是否更有意义。

https://docs.oracle.com/javase/tutorial/uiswing/concurrency/

每个窗口都不会在自己的单独线程上运行。只有一个EDT。每个窗口都在SAME线程EDT上运行。当EDT有机会时,您发送给EDT的每个Runnable将依次执行,一个接一个地执行。因此invokeLater()的“后期”部分。

答案 1 :(得分:0)

基本上所有的挥杆窗都与主线有关。 swing中的每个组件都以线程形式运行。完成事件控制后,再次返回主线程,等待事件发生。