对于在javafx中使用Platform.runLater()
感到有些困惑,因为我得到Platform.runLater()
会将可运行的参数发送到线程队列,并按顺序执行它,以防被多次调用,例如以及Platform.runLater()
是单个javafx线程
在我的javafx应用程序中,我不仅需要在javafx应用程序内部监听所有操作系统中的鼠标和键盘事件
当前我正在创建两个Timeline
所以我正在做以下事情:
class FirstTimeLineWrapperClass implements Runnable {
public void run() {
Timeline timeline1 = new Timeline(new KeyFrame(
Duration.seconds(1),
ae -> {
secondPassed++;
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
}
class SecondTimeLineWrapperClass implements Runnable {
public void run() {
Timeline timeline2 = new Timeline(new KeyFrame(
Duration.seconds(1),
ae -> {
secondPassed++;
}));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}
}
然后我打电话:
Platform.runLater(new FirstTimeLineWrapperClass());
Platform.runLater(new SecondTimeLineWrapperClass());
上面的内容有点混乱,但是为了澄清我的问题,
那么我们可以这样做吗,上面的代码可能出什么问题了?
并且如果Platform.runLater()
将在单个javafx线程中运行,那么上面的代码如何同时工作?
文档中提到
警告:正在从FX运行时引用正在运行的时间轴。如果未正确停止,无限时间轴可能会导致内存泄漏。所有具有动画属性的对象都不会被垃圾收集。
答案 0 :(得分:3)
动画不会创建任何其他线程,也不会在任何后台线程上运行。
您可以将FX Application Thread视为一个循环,用伪代码看起来像这样(实际细节要复杂得多):
while (applicationIsRunning()) {
if (anyEventsNeedHandling()) {
handleEvents();
}
processAnyRunnablesFromRunLaterQueue();
if (timeToUpdateScene()) {
if (animationsNeedProcessing()) {
processAnimations();
}
updateScene();
}
}
动画的本质工作方式是,正在运行的动画将其自身注册到上述主循环意识到的位置。动画可以确定是否该做某事-例如,在您的Timeline
中,关键帧每秒执行一次,因此Timeline
报告一个或多个关键帧是否到期相对容易进行处理,并在必要时调用事件处理程序。没有指定具体的机制,但这是基本功能。
请注意,play()
方法只是启动动画(即,将其注册到FX Application Thread循环中以对其进行检查)并立即退出。因此,在您的代码中,您在FX Application线程上快速连续地启动两个Timeline
,它们将立即一个接一个地启动(实际上几乎同时)。
因此,您可以启动多个动画,并且它们不会阻止FX Application Thread。通常的规则适用于在FX Application线程上执行的代码,适用于任何关键帧处理程序中的代码:它不应阻塞,也不需要花费很长时间来运行。
还请注意,如果将可运行对象添加到运行后期队列中的速度快于它们的执行速度,则将有效地阻止FX Application Thread,从而使UI响应性变差(或完全阻止)。