JavaFX计时器线程问题

时间:2016-12-03 17:35:02

标签: java multithreading javafx

我一直在尝试使用带有scenebuilder的JavaFX创建一个计时器,但是我在创建线程时遇到了一些问题。每当我点击开始按钮时,应用程序都会滞后,从不真正更新文本。我一直试图使用public class SecondClass extends Activity { EditText name,age; TextView text_name,text_age; String namer,ager; private String savedName,savedAge; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second_activity_layout); name=(EditText) findViewById(R.id.name); age=(EditText) findViewById(R.id.age); text_name=(TextView) findViewById(R.id.name_edit); text_age=(TextView) findViewById(R.id.name_age); if (savedInstanceState!=null) { savedInstanceState.get(savedName); name.setText(savedName); savedInstanceState.get(savedAge); age.setText(savedAge); } if (savedInstanceState==null) { Intent i=getIntent(); Bundle bundle=i.getExtras(); namer=bundle.getString("UName"); name.setText(namer); ager=bundle.getString("UAge"); age.setText(ager); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString(savedName,namer); outState.putString(savedAge,ager); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); if (savedInstanceState!=null) { savedInstanceState.get(savedName); name.setText(savedName); savedInstanceState.get(savedAge); age.setText(savedAge); } if (savedInstanceState==null) { Intent i=getIntent(); Bundle bundle=i.getExtras(); namer=bundle.getString("UName"); name.setText(namer); ager=bundle.getString("UAge"); age.setText(ager); } } },但如上所述,一切都落后了,结果就是如此。

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

Platform.runLater()

这是StopWatch.java类:

    @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) );
    }); 
}

感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您不限制线程的更新频率。通过这种方式,您可以发布这么多Runable的应用程序线程来执行,没有时间进行事件处理和布局,这使得您的应用程序以这种方式运行。

此外,您不会同步对布尔标志的访问,也不会使它们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进行更新。此课程的更新频率有限。