提问者:小点点

java.lang.IllegalState异常:使用石英时不在FX应用程序上


我尝试在quartz的任务调度中使用javafx alert:

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

消息do错误:

java.lang.:不在FX应用线程上;当前线程=DefaultQuartzScheduler_Worker-2Executou!


共1个答案

匿名用户

与大多数UI工具包一样,JavaFX是单线程的,不是线程安全的。一旦场景图形显示在窗口中,它只能在JavaFX应用程序线程上进行交互。有些对象必须在FX线程上实例化。否则会导致错误,就像你遇到的那样,或者完全是未定义的行为。如果你在一个后台线程上,你需要用FX线程安排一个动作,你可以使用< code > platform . run later(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();
    }
}

一些注意事项:

    < li >以上使用了lambda表达式。 < li >使用资源时,不要忘记关闭资源(例如< code>PreparedStatement,< code>ResultSet)。使用带资源的try。 < li >对< code>runLater的调用不等待< code>Runnable返回。 < li >这里有“未知副作用”注释,因为我不知道这些方法调用是否会修改UI。我已经将它们排除在< code>runLater调用之外,因为我假设它们不会。 < li >我找不到< code>Alerts a = new Alerts()的实际使用位置。 < li >名称< code>Resultado不符合局部变量的标准Java命名约定。 < li >请注意,适当缩进代码会使阅读和跟踪发生的事情更加容易。

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

如果对Java中的并发性没有起码的基本理解,将会阻碍您创建除了最琐碎的GUI应用程序之外的所有应用程序。我强烈建议您在继续之前研究一下这个主题。首先,请阅读以下内容:

  • 课程:并发
  • JavaFX中的并发

此外,BrianGoetz等人的一本关于这个主题的好书是《Java并发实践》。