【问题标题】:How to properly exit javaFX Platform.runLater如何正确退出 javaFX Platform.runLater
【发布时间】:2015-05-02 16:25:35
【问题描述】:

当我关闭应用程序时,下面的代码没有正确退出。我相信问题是我在哪里准确调用 system.exit 和 platform.exit....

hour_Label.textProperty().bind(hour);
minute_Label.textProperty().bind(minute);
second_Label.textProperty().bind(second);

new Thread(() -> 
{    
    for (;;) 
    {                 
        try 
        { 
            final SimpleDateFormat simpledate_hour = new SimpleDateFormat("h");
            final SimpleDateFormat simpledate_minute = new SimpleDateFormat("mm");
            final SimpleDateFormat simpledate_second = new SimpleDateFormat("s");
            Platform.runLater(new Runnable() {
                @Override public void run() 
                {
                    hour.set(simpledate_hour.format(new Date()));
                    minute.set(simpledate_minute.format(new Date()));
                    second.set(simpledate_second.format(new Date())); 
                }
            });
            Thread.sleep(200);                
        }
        catch (Exception e){logger.warn("Unexpected error", e); Thread.currentThread().interrupt(); Platform.exit(); System.exit(0);}
    }
}).start();

【问题讨论】:

  • “没有正确退出”是什么意思?
  • 当我关闭它时,我必须强制退出 OS X 上的应用程序

标签: java multithreading javafx exit platform


【解决方案1】:

将您的主题设为daemon thread

当唯一运行的线程都是守护线程时,Java 虚拟机退出。

你还需要让线程知道它应该退出。

import javafx.application.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import java.util.Date;
import java.util.concurrent.atomic.AtomicBoolean;

public class Sleeper extends Application{
    @Override
    public void start(Stage stage) throws Exception {
        Label time = new Label();

        AtomicBoolean shuttingDown = new AtomicBoolean(false);

        Thread thread = new Thread(() -> {
            while (!shuttingDown.get() && !Thread.interrupted()) {
                Platform.runLater(() -> time.setText(new Date().toString()));
                try {
                    Thread.sleep(1_000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        thread.setDaemon(true);
        thread.start();

        Button exit = new Button("Exit");
        exit.setOnAction(event -> {
            shuttingDown.set(true);
            thread.interrupt();
            Platform.exit();
        });

        stage.setScene(new Scene(new StackPane(time), 240, 40));
        stage.show();
    }
}

您无需在线程的异常处理程序中调用 Platform.exit() 或 System.exit(0)。

您可能会发现使用 JavaFX Task 更方便。任务文档解释了取消任务的方法。

但实际上,我不建议在您的示例中使用其他线程,而是使用时间轴,如 Sergey 在他对JavaFX periodic background task 的回答中的五秒奇迹中所举例说明的那样。

【讨论】:

    【解决方案2】:

    不要使用线程!请改用Timeline

    Timeline clock = new Timeline(
        new KeyFrame(Duration.seconds(0), evt -> {
            LocalTime now = LocalTime.now();
            hour.set(String.format("%d", now.getHour()));            
            minute.set(String.format("%02d", now.getMinute()));            
            second.set(String.format("%d", now.getSecond()));            
        }),
        new KeyFrame(Duration.seconds(1))
    );
    clock.setCycleCount(Animation.INDEFINITE);
    clock.play();
    

    由于Timeline 由FX 应用程序线程运行,您不需要通过Platform.runLater(...) 进行任何同步。除此之外,您可以根据需要启动和停止时间线,并在 FX 应用程序线程停止时自动终止。

    【讨论】:

      猜你喜欢
      • 2017-01-31
      • 2012-11-26
      • 1970-01-01
      • 1970-01-01
      • 2012-07-18
      • 2014-12-17
      • 1970-01-01
      • 2015-05-31
      相关资源
      最近更新 更多