JavaFX 多线程之 Task、Service、ScheduledService

您所在的位置:网站首页 java多线程交互 JavaFX 多线程之 Task、Service、ScheduledService

JavaFX 多线程之 Task、Service、ScheduledService

2024-07-12 14:24| 来源: 网络整理| 查看: 265

JavaFX 多线程之 Task、Service、ScheduledService 一、开发环境二、javafx.concurrent 包1、Worker 接口2、Task 类① 取消 Task② 显示后台 Task 的进度 3、Service 类4、WorkerStateEvent 类和状态转换5、ScheduledService 类① Task 成功完成② Task 失败 三、代码实现1、JavaFX 界面2、创建线程池3、通过扩展 Task 类创建 Task4、带返回结果的 Task5、绑定进度条的 Task6、获取 Task 返回的结果7、通过扩展 Service 类创建 Service8、ScheduledService 执行定时任务 四、示例代码

一、开发环境

IntelliJ IDEA 2020.2.3 + JDK 1.8 + JavaFX Scene Builder 2.0

二、javafx.concurrent 包

        JavaFX 场景图表示 JavaFX 应用程序的图形用户界面,它不是线程安全的,只能从 UI 线程(也称为 JavaFX 应用程序线程)访问和修改。在 JavaFX 应用程序线程上实现长时间运行的任务不可避免地会使应用程序 UI 无响应。最佳实践是在一个或多个后台线程上执行这些任务,并让 JavaFX 应用程序线程处理用户事件。

        如果有特殊要求或需要额外的代码处理能力,通过创建一个 Runnable 对象和一个新线程来实现后台 worker 是一种合适的方法。请注意,在某些时候必须与 JavaFX 应用程序线程通信,无论是结果还是后台任务的进度。

        对于大多数情况和大多数开发人员,推荐的方法是使用 javafx.concurrent 包提供的 JavaFX API,它负责与 UI 交互的多线程代码,并确保这种交互发生在正确的线程上。

        Java 平台通过 java.util.concurrent 包提供了一整套可用的并发库。 javafx.concurrent 包通过考虑 JavaFX 应用程序线程和 GUI 开发人员面临的其他约束来利用现有 API。

        javafx.concurrent 包由 Worker 接口和两个具体实现 Task 和 Service 类组成。 Worker 接口提供了一些 API,这些 API 对于后台 worker 与 UI 进行通信非常有用。 Task 类是 java.util.concurrent.FutureTask 类的一个完全可观察的实现。 Task 类使开发人员能够在 JavaFX 应用程序中实现异步任务。 Service 类执行任务。

        WorkerStateEvent 类指定了每当 Worker 实现的状态发生变化时发生的事件。 Task 和 Service 类都实现了 EventTarget 接口,因此支持监听状态事件。

在这里插入图片描述

1、Worker 接口

        Worker API 文档:Worker (JavaFX 2.2)

        Worker 接口定义了一个对象,该对象在一个或多个后台线程上执行某些工作。 Worker 对象的状态可以从 JavaFX 应用程序线程中观察和使用。

        Worker 对象的生命周期定义如下。创建时,Worker 对象处于 READY 状态。在计划进行工作后,Worker 对象将转换为 SCHEDULED 状态。之后,当 Worker 对象执行工作时,其状态变为 RUNNING。请注意,即使 Worker 对象在没有被调度的情况下立即启动,它也会首先转换为 SCHEDULED 状态,然后转换为 RUNNING 状态。成功完成的 Worker 对象的状态是 SUCCEEDED,value 属性设置为这个 Worker 对象的结果。否则,如果在 Worker 对象的执行过程中抛出任何异常,其状态将变为 FAILED,并且异常属性被设置为发生的异常的类型。在 Worker 对象结束之前的任何时间,开发人员都可以通过调用取消方法来中断它,该方法将 Worker 对象置于 CANCELED 状态。他们之间的关系如下图。

在这里插入图片描述

        ScheduledService 对象生命周期的区别可以在 ScheduledService 类部分找到。

        可以通过三个不同的属性(例如 totalWork,workDone 和 progress)获得由Worker对象完成的工作进度。

2、Task 类

        Task API 文档:Task (JavaFX 2.2)

        任务用于实现需要在后台线程上完成的工作逻辑。首先,需要扩展 Task 类。对 Task 类的实现必须覆盖 call 方法才能完成后台工作并返回结果。

        call 方法是在后台线程上调用的,因此该方法只能操作可以安全地从后台线程读取和写入的状态。例如,从 call 方法操作活动场景图会引发运行时异常。另一方面,Task 类旨在与 JavaFX GUI 应用程序一起使用,它确保对公共属性、错误或取消的更改通知、事件处理程序和状态的任何更改都发生在 JavaFX 应用程序线程上。在 call 方法中,您可以使用 updateProgress、updateMessage、updateTitle 方法,这些方法更新 JavaFX 应用程序线程上相应属性的值。但是,如果任务被取消,则调用方法的返回值将被忽略。

        请注意,Task 类适合 Java 并发库,因为它继承自实现 Runnable 接口的 java.utils.concurrent.FutureTask 类。因此,Task 对象可以在 Java 并发 Executor API 中使用,也可以作为参数传递给线程。您可以使用 FutureTask.run() 方法直接调用 Task 对象,该方法允许从另一个后台线程调用此任务。充分了解Java并发API将有助于了解JavaFX中的并发。

可以通过以下方式之一启动任务:

通过以给定任务作为参数启动线程: Thread th = new Thread(task); th.setDaemon(true); th.start();

通过使用 ExecutorService API: ExecutorService.submit(task);

        Task 类定义了一个不能重复使用的一次性对象。 如果需要可重用的 Worker 对象,请使用 Service 类。

① 取消 Task

        Java 中没有可靠的方法来停止进程中的线程。 但是,只要对任务调用取消,任务就必须停止处理。 任务应该在其工作期间定期检查它是否被调用方法主体中的 isCancelled 方法取消。 下面的示例显示了检查取消的 Task 类的正确实现。

import javafx.concurrent.Task; Task task = new Task() { @Override protected Integer call() throws Exception { int iterations; for (iterations = 0; iterations


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3