Initial Threads

每个程序都有一组应用程序逻辑开始的线程。在标准程序中,只有一个这样的线程:调用程序类的main方法的线程。在 applet 中,初始线程是构造 applet 对象并调用其initstart方法的线程。这些动作可能发生在单个线程上,也可能发生在两个或三个不同的线程上,具体取决于 Java 平台的实现。在本课中,我们将这些线程称为初始线程。

在 Swing 程序中,初始线程没有很多工作要做。他们最重要的工作是创建一个Runnable对象,该对象初始化 GUI 并安排该对象在事件分发线程上执行。一旦创建了 GUI,程序就主要由 GUI 事件驱动,每个 GUI 事件都会导致在事件分配线程上执行简短任务。应用程序代码可以在事件分配线程(如果它们迅速完成,以免干扰事件处理)上或工作线程(对于 Long 时间运行的任务)上调度其他任务。

初始线程通过调用javax.swing.SwingUtilities.invokeLaterjavax.swing.SwingUtilities.invokeAndWait调度 GUI 创建任务。这两种方法都采用一个参数:Runnable定义新任务。它们的唯一区别由它们的名称表示:invokeLater只是计划任务并返回; invokeAndWaitawait 任务完成后再返回。

您可以在整个 Swing 教程中看到此示例:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        createAndShowGUI();
    }
});

在小应用程序中,必须使用invokeAndWaitinit方法启动 GUI 创建任务。否则,init可能会在创建 GUI 之前返回,这可能会导致 Web 浏览器启动 Servlets 的问题。在任何其他类型的程序中,调度 GUI 创建任务通常是初始线程要做的最后一件事,因此使用invokeLater还是invokeAndWait都无关紧要。

为什么初始线程不能简单地创建 GUI 本身?因为几乎所有创建或与 Swing 组件交互的代码都必须在事件分发线程上运行。下一节将进一步讨论此限制。