Swing 运行 中的 JFrame windows 在它们自己单独的线程上吗?

Do JFrame windows in Swing run on their own separate threads?

我有三个问题,它们是紧密相关的,因为它们相互脱胎而出,代表了一个思路,所以我将它们发布在一个问题下。如果我单独发布它们,这对我构建问题的全局没有帮助。

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

Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI. In the following example the invokeLater call queues the Runnable object doHelloWorld on the event dispatching thread and then prints a message.

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

invokeLater 方法仅在应用程序的主线程上安排主要 window 创建和设置其调度程序/消息泵,而不是在单独的线程上.它通过 发布 消息来创建 window 并将其设置在 主/主应用程序线程 上。换句话说,主线程对我们说,"The window you are asking me to create will be created after I am done doing everything else that is on my plate right now."

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

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

3) 我在创建 window 的函数和作为 window 的消息循环的函数中打印出当前线程 ID,它们都是不同的线程。那么,Swing 中的每个 window 都在自己的线程上运行?那太疯狂了。你能向我解释一下这里发生了什么吗?另外,如果您能用一两段解释在 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()));
    }
}

Output:

Main thread 1 started.

Main window loop running on thread 14.

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

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

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

每个 window 不会 运行 在其自己的单独线程上。只有一个 EDT。每个 windows 运行s 在同一个线程上,即 EDT。当 EDT 有机会时,您发送给 EDT 的每个 Runnable 都会按顺序执行,一个接一个。因此 invokeLater().

的 "later" 部分

基本上所有的摆动windows都绑定到主线程。 swing 中的每个组件都作为线程运行。完成一个事件控制后再次returns回到主线程等待事件发生