我对使用 Platform.runLater()
在javafx中,因为我得到了 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运行时引用。如果不正确停止,无限时间线可能会导致内存泄漏。所有带有动画属性的对象都不会被垃圾回收。
动画不会创建任何额外的线程,也不会在任何后台线程上运行。
你可以把FX应用线程看作是一个循环,在伪代码中,它看起来像这样(实际细节要复杂得多)。
while (applicationIsRunning()) {
if (anyEventsNeedHandling()) {
handleEvents();
}
processAnyRunnablesFromRunLaterQueue();
if (timeToUpdateScene()) {
if (animationsNeedProcessing()) {
processAnimations();
}
updateScene();
}
}
动画本质上的工作方式是,一个正在运行的动画在某个地方注册了自己,而上面描述的主循环知道它。动画可以确定是否是时候做一些事情--例如,在你的 Timeline
的关键帧每秒钟都会执行一次,所以它相对容易让 Timeline
来报告是否有一个或多个关键帧需要处理,如果需要,事件处理程序将被调用。实际的机制并没有指定,但这是基本功能。
请注意 play()
方法只是启动动画(即为FX应用线程循环注册它以检查它)并立即退出。所以在你的代码中,你启动了两个 Timeline
在FX应用线程上快速地连续启动多个动画,它们将一个接一个地立即启动(几乎在同一时间)。
因此,您可以启动多个动画,而且它们不会阻塞FX应用程序线程。在FX Application线程上执行的代码的通常规则适用于任何关键帧处理程序中的代码:它不应该阻塞,也不应该花费很长的时间来运行。
另外要注意,如果你把可运行的代码添加到运行后期队列中,其速度超过了它们的执行速度,你将有效地阻塞FX应用线程,使UI的响应速度变差(或者完全阻塞它)。