【问题标题】:java.lang.IllegalStateException:Not on FX application when using quartzjava.lang.IllegalStateException:使用石英时不在 FX 应用程序上
【发布时间】:2019-07-14 12:03:40
【问题描述】:

我正在尝试在石英的任务计划中使用 javafx 警报:

public class ChecarJob implements Job{
    private Connection con;
    public ChecarJob() {
        this.con = new ConnectionFactory().getConnection();
    }
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("Executou!");
                try {
                    String verStatus = "SELECT COUNT(*) FROM equipamento_requisicao";
                    PreparedStatement stmt = con.prepareStatement(verStatus);
                        ResultSet rsStatus = stmt.executeQuery();
                        if(rsStatus.next()){
                        Alerts a = new Alerts();
                        int Resultado = rsStatus.getInt(1);
                        if(Resultado>Sessao.getInstancia().getQtdRegistroBD()){
                        Sessao.getInstancia().setQtdRegistroBD(Resultado);
                                                Alert alert = new Alert(Alert.AlertType.INFORMATION);
                        alert.setTitle("SUCESS");
                        alert.setHeaderText("SUCESS");
                        alert.setContentText("SUCESS");
                        alert.showAndWait();
                        }
                        else if(Resultado<Sessao.getInstancia().getQtdRegistroBD()){
                        Alert alert = new Alert(Alert.AlertType.INFORMATION);
                        alert.setTitle("FAIL");
                        alert.setHeaderText("FAIL");
                        alert.setContentText("FAIL");
                        alert.showAndWait();
                        Sessao.getInstancia().setQtdRegistroBD(Resultado);
                        } 
                        else{
                        //aq não irei fazer nada.
                        }
                        }
                    }catch (Exception e) {
            e.printStackTrace();
                    }
    }   

}

在我的主课中调用:

public void start(Stage stage) throws Exception {
    JobDetail j = JobBuilder.newJob(ChecarJob.class).build();
    Trigger t = TriggerBuilder.newTrigger().withIdentity("CroneTrigger")
            .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(60).repeatForever()).build();
    Scheduler s = StdSchedulerFactory.getDefaultScheduler();
    s.start();
    s.scheduleJob(j,t);

msg 出错:

java.lang.IllegalStateException:不在 FX 应用程序线程上; currentThread = DefaultQuartzScheduler_Worker-2Executou!

【问题讨论】:

标签: javafx


【解决方案1】:

JavaFX 与大多数 UI 工具包一样,是单线程的,不是线程安全的。一旦场景图在窗口中显示,它只能在 JavaFX 应用程序线程 上进行交互。并且某些对象必须在 FX 线程上实例化。否则可能会导致错误,就像您遇到的那样,或者只是完全未定义的行为。如果您在后台线程上并且需要使用 FX 线程安排操作,则可以使用 Platform.runLater(Runnable)(链接到 Javadoc)。

您的代码不是一个最小且完整的示例,因此我无法确定所有内容的作用。不过,一般来说,我会先将所有与 Alert 实例相关的代码移到 runLater 调用中。

public void execute(JobExecutionContext context) throws JobExecutionException {
    System.out.println("Executou!");
    try {
        String verStatus = "SELECT COUNT(*) FROM equipamento_requisicao";
        PreparedStatement stmt = con.prepareStatement(verStatus);
        ResultSet rsStatus = stmt.executeQuery();
        if (rsStatus.next()) {
            Alerts a = new Alerts(); // what does this do?
            int Resultado = rsStatus.getInt(1);
            if (Resultado > Sessao.getInstancia().getQtdRegistroBD()) {
                Sessao.getInstancia().setQtdRegistroBD(Resultado); // unknown side-effects
                Platform.runLater(() -> {
                    Alert alert = new Alert(Alert.AlertType.INFORMATION);
                    alert.setTitle("SUCESS");
                    alert.setHeaderText("SUCESS");
                    alert.setContentText("SUCESS");
                    alert.showAndWait();
                });
            } else if (Resultado < Sessao.getInstancia().getQtdRegistroBD()) {
                Platform.runLater(() -> {
                    Alert alert = new Alert(Alert.AlertType.INFORMATION);
                    alert.setTitle("FAIL");
                    alert.setHeaderText("FAIL");
                    alert.setContentText("FAIL");
                    alert.showAndWait();
                });
                Sessao.getInstancia().setQtdRegistroBD(Resultado); // unknown side-effects
            } else {
                //aq não irei fazer nada.
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

一些注意事项:

  • 以上使用lambda expressions
  • 完成后不要忘记关闭资源(例如PreparedStatementResultSet)。使用try-with-resources
  • runLater 的调用不会等待Runnable 返回。
  • 存在“未知的副作用”cmets,因为我不知道这些方法调用是否会修改 UI。我将他们排除在 runLater 电话之外,假设他们没有。
  • 我找不到Alerts a = new Alerts() 的实际使用位置。
  • 名称 Resultado 不遵循局部变量的标准 Java 命名约定。
  • 请注意,正确缩进代码可以更轻松地阅读和跟踪正在发生的事情。

我是java新手,对线程不太了解

至少对 Java 中的并发性没有基本的了解会阻碍您创建除了最琐碎的 GUI 应用程序之外的所有应用程序。我强烈建议您在继续之前研究这个主题。作为开始,请阅读以下内容:

另外,关于该主题的一本好书是 Brian Goetz 等人的Java Concurrency in Practice

【讨论】:

  • 谢谢我忘记关闭状态并准备好这些警报我将使用以防我在数据库中添加了新记录,因此我每 10 分钟执行一次例程
  • 我发现这个用于修复关闭:stage.setOnCloseRequest(e -> { try { s.shutdown(); Platform.exit(); System.exit(0); } catch (SchedulerException ex ) { Logger.getLogger(Principal.class.getName()).log(Level.SEVERE, null, ex); } });
  • 我想不通如何覆盖停止你能帮我吗?
猜你喜欢
  • 2015-06-09
  • 1970-01-01
  • 2013-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-24
相关资源
最近更新 更多