> 文档中心 > Java:JavaFX中的多线程

Java:JavaFX中的多线程

  几乎所有的 GUI 平台都使用单线程事件调度模型,JavaFX 也不例外。JavaFX 在处理多线程编程时遇到了一系列独特的挑战。原因是 JavaFX 主要设计为以或多或少的线性方式工作。所有用户界面事件都在 JavaFX 应用程序线程中处理。为了充分利用现代多核机器,JavaFX 应该能够利用 Java 编程语言的多线程。本文试图解释JavaFX编程外围下的多线程原理。

  JavaFX 场景图不是线程安全的

  JavaFX UI 设计从一个阶段开始。它是顶级 UI 容器。但是,Stage 的实际实现取决于部署它的平台,例如网页、平板电脑或桌面。JavaFX 场景在由节点代表的演员在视觉上相互交互的舞台上播放。场景是场景图中所有内容的容器。JavaFX 中多线程的主要问题是场景图本身不是线程安全的。它被建模为在单个 JavaFX 应用程序线程上执行。在 JavaFX-Launcher 线程中调用构造函数和初始化方法 init()。在 JavaFX 应用程序线程中调用 start() 和 stop() 方法。这些事件也在 JavaFX 应用程序线程上进行处理。因此,现场的任何实时操作都必须单独在主应用程序线程上完成。

  未附加到现场场景的节点可以在其他线程中创建和操作。但是,一旦它们被附加,它们就不能被多个线程操作而不会有不正确结果的风险,因此可能会破坏场景图。在主应用程序线程上应用的任何长时间运行的任务都必然会冻结用户界面。从多线程编程的角度来看,这显然是不可接受的。JavaFX 应用程序中的线程安全无法通过同步线程操作来实现。我们必须确保操作场景图的程序只能从 JavaFX 应用程序线程中执行此操作。因此,JavaFX 中的多线程必须以不同的方式处理。

  线程限制

  线程限制是一种与JavaFX一起应用来实现多线程的技术。这是一种只允许一个线程访问代码的线程不安全部分的技术,从而确保以简单的方式实现线程安全。然而,这是在 Java 编程的许多其他领域中应用的常用技术。线程限制中的任何数据也称为线程本地。它是线程安全的,因为线程本地环境中不能存在竞争,并且不需要锁定数据。这种类型的线程安全可以通过池化 JDBC 对象看到。在典型的服务器应用程序中,线程从连接池中获取连接对象。它使用该连接处理单个请求周期并将其返回到池中。在返回对它的引用之前,池不会将相同的连接对象分配给任何其他线程。因此,模式是连接管理隐式地将连接对象限制在特定线程中,并在请求期间保留或限制它。当应用于 JavaFX 编程时,这种线程管理机制被证明是非常有用的。

  

 

  在 JavaFX 中实现多线程

  尽管在重型 JavaFX 应用程序线程上按顺序应用 GUI 组件操作的一些次要和简短的任务是可以接受的,但只有当它们无法完全避免或产生可预测的后果时才是正确的。但是,如果任务很长,并且为了响应用户交互,则必须在单独的线程中处理它,因为当线程绑定到该任务时,JavaFX 应用程序线程无法呈现控件或响应事件。这肯定会导致 GUI 冻结并变得无响应。将长时间运行的任务委托给单独的线程可以释放 JavaFX 应用程序线程以保持响应并可以继续管理 GUI 交互。但是,GUI 必须根据运行线程的计算结果进行更新。

  runLater 方法

  JavaFX 提供了多种机制来从其他线程更新与场景图关联的 GUI。一种技术是调用 Platform 类中定义的静态 void runLater (Runnable runnable) 方法。根据 Java API 文档,此方法在未来某个未指定的时间在 JavaFX 应用程序线程上运行指定的 Runnable。此方法可以从任何线程调用,它将 Runnable 发布到事件队列,然后立即返回给调用者。但是,需要注意的是应用程序应该避免过多的挂起的 Runnables 泛滥;否则,这可能会使应用程序无响应。因此,此类 Runnables 应该只执行小的更新以降低风险。

  使用任务和工作人员

  任何计算密集型任务都必须通过使用单独的工作线程与 JavaFX 的主应用程序线程分离。JavaFX 提供了一个完整的包来处理多线程和并发的问题。为此,有一个名为 Worker 的接口、一个名为 Task 的抽象类和 ScheduledService。Task 基本上是一个 Worker 实现,非常适合实现长时间运行的计算。Task 类扩展了 FutureTask,因此也支持 Runnable、Future 和 RunnableFuture 接口。由于其遗留/继承,这个类可以以各种方式使用。

  结论

  本文展示了 JavaFX 多线程的基础知识。它还试图说明 JavaFX 中的多线程与常规 Java 中的多线程有一些不同之处,JavaFX 中多线程的核心类在 javafx.concurrent 包中定义。