栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

JavaFX 2:背景和Platform.runLater与任务/服务

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaFX 2:背景和Platform.runLater与任务/服务

Task
Service
课程旨在鼓励良好做法,在GUI编程的一些(但不是全部)常见的场景正确使用并发。

典型的情况是,应用程序需要执行一些逻辑来响应可能需要很长时间(可能是很长的计算,或更常见的是数据库查找)的用户操作。该过程将返回结果,然后将其用于更新UI。如您所知,长时间运行的进程需要在后台线程上执行以保持UI响应,并且UI的更新必须在FX
Application Thread上执行。

Task
类提供这种功能的抽象,并且表示被执行,并产生一个结果的“一次性”的任务。该
call()
方法将在后台线程上执行,并设计为返回进程的结果,并且在FX
Application线程上会通知事件完成时的事件侦听器。强烈建议开发人员
Task
使用不可变状态初始化实现,并让该
call()
方法返回不可变对象,以确保后台线程和FX
Application Thread之间的正确同步。

这些类型的任务还有其他共同要求,例如,随着任务的进展更新消息或进度。应用程序可能还需要监视类的生命周期状态(等待运行,正在运行,已完成,因异常而失败等)。正确编程非常困难,因为它必然涉及在两个不同线程中访问可变状态,并且许多应用程序开发人员都不知道其细微之处。本

Task
类提供简单的挂钩这种功能,并采取所有的同步服务。

要使用此功能,只需要创建一个

Task
它的
call()
方法返回的计算结果,登记时从状态转换的处理程序
RUNNING
SUCCEEDED
,并运行在后台线程任务:

final Task<MyDataType> task = new Task<MyDataType>() {    @Override    public MyDataType call() throws Exception {        // do work here...        return result ;    }};task.setonSucceeded(new EventHandler<WorkerStateEvent>() {    @Override    public void handle(WorkerStateEvent event) {        MyDataType result = task.getValue(); // result of computation        // update UI with result    }});Thread t = new Thread(task);t.setDaemon(true); // thread will not prevent application shutdownt.start();

它在幕后的工作方式是

Task
维护一个
state
属性,该属性是使用常规JavaFX实现的
ObjectProperty
。在
Task
本身被包裹在一个私人的实施
Callable
Callable
执行是传递给父类的构造对象。因此,
Callable
call()
方法实际上是在后台线程中执行的方法。所述
Callable
call()
方法是这样实现的:

  1. 安排FX Application线程上的调用(即使用
    Platform.runLater()
    ),
    state
    以将
    SCHEDULED
    ,更新为,然后更新为
    RUNNING
  2. 调用的
    call()
    方法
    Task
    (即用户开发的
    call()
    方法)
  3. 安排对FX Application Thread的调用,以将
    value
    属性更新为
    call()
    方法的结果
  4. 安排对FX Application Thread的调用,以将该
    state
    属性更新为
    SUCCEEDED

当然,这最后一步将调用在

state
属性中注册的侦听器,并且由于状态更改是在FX Application
Thread上调用的,因此这些侦听器的
handle()
方法也将被调用。

要全面了解其工作原理,请参见源代码。

通常,应用程序可能需要多次执行这些任务,并监视代表所有进程的当前状态(即“正在运行”现在意味着一个实例正在运行,等等)。的

Service
类简单地通过为此提供了一个包装
createTask()
方法。当
Service
启动时,它
Task
通过调用获取实例,通过实例
createTask()
执行该实例
Executor
,并相应地转换其自身的状态。

当然,有很多并发用例不适合(至少是完全不适合)

Task
Service
实现。如果您有一个
Thread
在整个应用程序运行期间都在运行的背景(因此它表示一个连续的过程,而不是一次性的任务),则
Task
该类不是一个很好的选择。例如,游戏循环或(可能)轮询。在这些情况下,最好使用自己的
Thread
with
Platform.runLater()
来更新UI,但当然,您必须处理两个线程都可以访问的任何变量的正确同步。以我的经验,值得花些时间考虑这些需求是否可以重新组织成适合于
Task
或的东西。
Service
模型,好像可以做到这一点一样,生成的代码结构通常更简洁,更易于管理。当然,在某些情况下并非如此,但在这种情况下使用
Thread
Platform.runLater()
是合适的。

关于轮询的最后一项评论(或对定期计划的后台任务的其他任何要求)。这个

Service
班级看起来像是一个很好的候选人,但是事实证明要有效地管理周期性非常困难。JavaFX
8引入了一个
ScheduledService
很好地处理此功能的类,并且还增加了对诸如后台任务反复失败等情况的处理。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/497862.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号