我对在javafx中使用Platform.runLater()
感到有点困惑,因为Platform.runLater()
会将可运行的参数发送到线程队列,并按顺序执行它,以防被多次调用,而且Platform.runLater()
是单个javafx线程。
在我的javafx应用程序中,我需要侦听所有操作系统中的鼠标和键盘事件,而不仅仅是在javafx应用程序中。
目前我正在创建两个时间线
所以我做的事情如下:
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运行时引用正在运行的时间线。如果不正确停止,无限时间线可能会导致内存泄漏。所有具有动画属性的对象都不会被垃圾回收。
发布于 2020-06-11 18:18:23
动画不会创建任何额外的线程,也不会在任何后台线程上运行。
您可以将FX应用程序线程看作一个循环,在伪代码中,它看起来如下(实际细节要复杂得多):
while (applicationIsRunning()) {
if (anyEventsNeedHandling()) {
handleEvents();
}
processAnyRunnablesFromRunLaterQueue();
if (timeToUpdateScene()) {
if (animationsNeedProcessing()) {
processAnimations();
}
updateScene();
}
}
动画本质上的工作方式是,运行中的动画注册到上面描述的主循环所知道的某个地方。动画可以确定是否需要做一些事情--例如,在Timeline
中,关键帧每秒钟执行一次,因此Timeline
相对容易地报告一个或多个关键帧是否需要处理,如果有必要,将调用事件处理程序。这方面的实际机制没有具体说明,但这是基本功能。
注意,play()
方法只是启动动画(即为循环注册动画以检查动画)并立即退出。因此,在您的代码中,在FX线程上快速地启动两个Timeline
,它们将一个接一个地启动(实际上几乎同时启动)。
因此,您可以启动多个动画,它们不会阻止FX应用程序线程。通常的规则适用于在FX Application线程上执行的代码,适用于任何关键帧处理程序中的代码:它不应该阻塞,也不应该花很长时间运行。
还需要注意的是,如果将runnables添加到运行后队列中的速度超过了它们的执行速度,那么将有效地阻止FX应用程序线程,从而导致UI响应能力差(或者完全阻塞它)。
https://stackoverflow.com/questions/62330652
复制相似问题