【问题标题】:JavaFX timer thread issuesJavaFX 计时器线程问题
【发布时间】:2017-04-18 10:45:51
【问题描述】:

我一直在尝试使用 JavaFX 和 scenebuilder 创建一个计时器,但是我在创建线程时遇到了一些问题。每当我点击开始按钮时,应用程序就会滞后并且永远不会真正更新文本。我一直在尝试使用Platform.runLater(),但如上所述,一切都落后了,因此。

以下是控制计时器的方法,链接到 FXML 文件中的特定按钮:

    @FXML
private void startTimer(){
    System.out.println("started");
    stopWatch.startTimer();

}

@FXML
private void pauseTimer(){
    stopWatch.pauseTimer(); 
}

@FXML
private void stopTimer(){
    System.out.println("stopped");
    stopWatch.stopTimer();
}

@FXML
public void updateTimer(long dT){

    //System.out.println(((dT/6000)%1000)+":"+String.valueOf((dT/1000)%1000)+","+String.valueOf((dT)%1000));
    Platform.runLater(() ->{
        timer.setText(String.valueOf(dT/1000) );
    }); 
}

这里是 StopWatch.java 类:

package sled.timer.address.model;

import sled.timer.address.view.PersonOverviewController;

public class StopWatch implements Runnable{

private Thread runThread; 
public boolean running = false; 
public boolean paused = false; 


private long summedTime = 0; 

PersonOverviewController personOverviewController; 

String time = ""; 

public void count(){

}
public StopWatch(PersonOverviewController personOverviewController){
    this.personOverviewController = personOverviewController; 

}
public void startTimer(){
    running  = true; 
    paused = false; 

    runThread = new Thread(this); 
    runThread.start(); 
}

public void pauseTimer(){
    paused = true; 
}

public void stopTimer(){
    running = false; 
    paused = false; 
}
@Override
public void run() {
    // TODO Auto-generated method stub
    long startTime = System.currentTimeMillis(); 
    while(running && !paused){
        personOverviewController.updateTimer(summedTime + (System.currentTimeMillis() - startTime));
    }
    if(paused)
        summedTime += System.currentTimeMillis() - startTime; 

    else 
        summedTime = 0; 

}

public long getSummedTime(){
    return summedTime; 
}

感谢任何帮助。

【问题讨论】:

    标签: java multithreading javafx


    【解决方案1】:

    您不限制线程的更新频率。这样一来,您就可以发布这么多 Runables 以供应用程序线程执行,以至于几乎没有时间进行事件处理和布局,从而使您的应用程序以这种方式运行。

    此外,您不同步对布尔标志的访问,也不将它们设为volatile,这意味着值更改不一定对其他线程可见。

    相反,您应该确保在最后一个 Runnable 开始之前不再发布更新:

    private final Object updaterLock = new Object();
    private final boolean updating = false;
    private final long value; 
    
    public void updateTimer(long dT) {
        synchronized (updaterLock) {
            value = dT;
            if (!updating) {
               updating = true;
               Platform.runLater(() -> {
                   synchronized (updaterLock) {
                       updating = false;
                       timer.setText(Long.toString(value/1000));
                   }
                });
            }
        }
    }
    
    public class StopWatch implements Runnable{
    
        ...
    
        public volatile boolean running = false; 
        public volatile boolean paused = false; 
    

    不过,请考虑使用the AnimationTimer class 进行更新。这个类的更新频率是有限的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-16
      • 2021-09-25
      • 1970-01-01
      • 1970-01-01
      • 2016-11-13
      • 1970-01-01
      相关资源
      最近更新 更多