Multithreading JavaFX时间轴动画性能差
我目前正在创建一个非常简单的JavaFX程序,模拟城市之间运送乘客的飞机和船只。到目前为止,我已经能够使飞机在几个城市进行短途飞行,但问题是,当我添加超过3或4架飞机时,动画速度非常慢 我正在做的是使用Timeline类作为我的主游戏循环,清除并重新绘制画布上每帧60 FPS的平面图像。以下是时间表部分:Multithreading JavaFX时间轴动画性能差,multithreading,animation,javafx,Multithreading,Animation,Javafx,我目前正在创建一个非常简单的JavaFX程序,模拟城市之间运送乘客的飞机和船只。到目前为止,我已经能够使飞机在几个城市进行短途飞行,但问题是,当我添加超过3或4架飞机时,动画速度非常慢 我正在做的是使用Timeline类作为我的主游戏循环,清除并重新绘制画布上每帧60 FPS的平面图像。以下是时间表部分: Timeline gameLoop = new Timeline(); gameLoop.setCycleCount( Timeline.INDEFINITE ); KeyFrame
Timeline gameLoop = new Timeline();
gameLoop.setCycleCount( Timeline.INDEFINITE );
KeyFrame keyFrame = new KeyFrame(
Duration.seconds(0.017),
new EventHandler<ActionEvent>()
{
public void handle(ActionEvent ae)
{
dynamicGC.clearRect(0, 0, 1280, 800);
for (Plane plane : Spawner.planeList)
{
if(plane.isInFlight()) plane.Draw(dynamicGC);
}
}
});
gameLoop.getKeyFrames().add(keyFrame);
gameLoop.play();
下面是在Plane类中定义的run()方法:
public void run() {
int routeCounter = 0;
int direction = 1;
boolean active = true;
double recordedTime = 0.0;
double aParameter = 0.0;
while(active) {
if (inFlight) {
double tmpTime = System.currentTimeMillis();
double timeDifference = tmpTime - recordedTime;
recordedTime = tmpTime;
double change = planeVelocity * (timeDifference) * direction;
xCoordinate += change;
yCoordinate += change * aParameter;
if ( Math.abs(xCoordinate - Spawner.airportList.get(nextAirport).getXCoordinate()) < Spawner.airportList.get(nextAirport).getDetectionPrecision()
&& Math.abs(yCoordinate - Spawner.airportList.get(nextAirport).getYCoordinate()) < Spawner.airportList.get(nextAirport).getDetectionPrecision()) {
inFlight = false;
routeCounter++;
}
} else {
if(routeCounter < plannedRoute.size() ) {
nextAirport = plannedRoute.get(routeCounter);
aParameter = (Spawner.airportList.get(nextAirport).getYCoordinate() - this.yCoordinate)/
(Spawner.airportList.get(nextAirport).getXCoordinate() - this.xCoordinate);
if (Spawner.airportList.get(nextAirport).getXCoordinate() < this.xCoordinate) {
direction = -1;
} else direction = 1;
recordedTime = System.currentTimeMillis();
inFlight = true;
}
else active = false;
}
}
}
public void run(){
int routeCounter=0;
int方向=1;
布尔活动=真;
双记录时间=0.0;
双参数=0.0;
while(活动){
国际单项体育联合会(机上){
double tmpTime=System.currentTimeMillis();
双时差=tmpTime-记录的时间;
记录的时间=tmpTime;
双变=平面速度*(时差)*方向;
xCoordinate+=变化;
Y坐标+=变化*参数;
if(Math.abs(xCoordinate-Spawner.airportList.get(nextAirport.getXCoordinate())
我知道代码非常混乱,但现在我想知道为什么动画速度会如此缓慢。我不确定我是否正确使用了线程。此外,我还尝试了一些解决方案,如缓存画布和组节点,如在问题的答案中,但没有任何效果
编辑:看来是线程减慢了程序的执行速度
每次在JavaFX应用程序线程中使用此处理程序按下某个按钮时,我都会创建一个新平面(以及一个新线程):
@FXML
private void handleNewPassengerPlaneCreated(ActionEvent event) {
ArrayList<Integer> route = new ArrayList<>();
int startingAirport = Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
for(int i = 0; i < 3; i++) {
int addedAirport = Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
if ( addedAirport != startingAirport)
route.add(addedAirport);
}
System.out.println(Spawner.airportList.get(startingAirport).xCoordinate + " " + Spawner.airportList.get(startingAirport).yCoordinate );
PassengerPlane plane = new PassengerPlane(Spawner.airportList.get(startingAirport).xCoordinate,
Spawner.airportList.get(startingAirport).yCoordinate, "ID", 10, 1000, route, 300);
Spawner.planeList.add(plane);
new Thread(plane).start();
}
@FXML
已创建私有void HandlenewPassengerPlane(ActionEvent事件){
ArrayList路由=新建ArrayList();
int startingAirport=Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
对于(int i=0;i<3;i++){
int addDairport=Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
if(addedAirport!=启动机场)
路线。添加(AddDairPort);
}
System.out.println(Spawner.airportList.get(startingAirport.xCoordinate+“”+Spawner.airportList.get(startingAirport.yccoordinate);
乘客飞机=新乘客飞机(Spawner.airportList.get(startingairplane).xCoordinate,
产卵器。机场列表。get(startingAirport)。yCoordinate,“ID”,101000,route,300);
产卵器。平面列表。添加(平面);
新螺纹(平面).start();
}
您应该使用不同的方法。看一看表中的答案
您应该使用时间线,而不是时间线,并在其中更新画布
关于您的问题:一个问题可能是您将线程与JavaFX线程混合在一起,这可能会导致问题,如果没有看到完整的代码就无法判断>我有一个,但是有一些事情您可能需要考虑,这可以极大地提高代码的性能:
路径转换
- 为正在飞行的飞机创建模型存储(可以是简单的列表或地图)
- 创建一个工作线程(很可能是一个线程)。这个将在UI应用程序线程的每个脉冲上调用,它应该等于您的帧速率。在该线程中,您可以更新存储中所有平面的位置,并更新UI中平面的位置。看看这个
从代码中我可以看到,您正在为每个平面创建一个单独的线程。线程是昂贵的对象,特别是对于每次运行线程时只需要几个cpu周期的任务。然后,你必须考虑线程切换的成本超过实际计算时间。因此,在使用线程时,请确保将其用于长时间运行的任务。我想知道为什么要使用画布来实现此目的。可能只是因为您已经习惯了AWT或类似的框架。场景图更适合这种问题。只需将场景图中的一些对象放置在它们的初始位置,然后在一个AnimationTimer中更新它们的位置和方向以及其他内容,您就完成了。问题在于我没有在run()方法中调用Thread.sleep(time),当我在时间=10的情况下添加它时,动画开始顺利运行。我将时间线更改为AnimationTimer,不幸的是,它仍然是一样的。看来问题在于线程。我已经做了一个按钮,它产生了一个线程
@FXML
private void handleNewPassengerPlaneCreated(ActionEvent event) {
ArrayList<Integer> route = new ArrayList<>();
int startingAirport = Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
for(int i = 0; i < 3; i++) {
int addedAirport = Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
if ( addedAirport != startingAirport)
route.add(addedAirport);
}
System.out.println(Spawner.airportList.get(startingAirport).xCoordinate + " " + Spawner.airportList.get(startingAirport).yCoordinate );
PassengerPlane plane = new PassengerPlane(Spawner.airportList.get(startingAirport).xCoordinate,
Spawner.airportList.get(startingAirport).yCoordinate, "ID", 10, 1000, route, 300);
Spawner.planeList.add(plane);
new Thread(plane).start();
}