【问题标题】:Javafx UI not responding after it runs TaskJavafx UI 在运行任务后没有响应
【发布时间】:2022-01-21 01:14:19
【问题描述】:

我正在开发一个 javafx 应用程序。由于我需要显示数据库中的一些数据,我开始了解在 Javafx 中使用Task。在看到 SO 上的solution 后,我尝试实现它。为了检查它是否有效,我只是打印了一个从我的数据库中获得的 HashTable 的团队列表。

当我第一次启动应用程序时,数据已成功获取并显示在我的控制台上,但是当我切换场景并尝试切换回主页(正在获取数据的位置)时,UI 完全冻结并显示它甚至不显示场景。

Home.java

public class Home implements Initializable {

    private Executor executor;
    private TeamsDAO teamsDAO;

@Override
    public void initialize(URL url, ResourceBundle resourceBundle)  {

        try{
            teamsDAO = new TeamsDAO();
        }catch (SQLException e){
            e.printStackTrace();}

        executor = Executors.newCachedThreadPool(runnable -> {
            Thread th = new Thread(runnable);
            th.setDaemon(true);
            return th;
        });

        printTeams();
    }

public void printTeams() {
        Task<Hashtable<Integer, String>> displayTask = new Task<Hashtable<Integer, String>>() {
            @Override
            protected Hashtable<Integer, String> call() throws Exception {
                return teamsDAO.getTeams();
            }
        };

        displayTask.setOnFailed(e -> {
            displayTask.getException().printStackTrace();
        });

        displayTask.setOnSucceeded(e -> {
            cricProTitle.setText(displayTask.getValue().get(2));
        });

        executor.execute(displayTask);
    }
}

我正在使用 HikariCP 作为 postgresql 的数据库连接池。

TeamsDAO.java

public class TeamsDAO {

    private Connection conn;

    public TeamsDAO() throws SQLException {
        this.conn = DataSource.getConnection();
    }

    public Hashtable<Integer, String> getTeams() throws SQLException {
        try (PreparedStatement pst = conn.prepareStatement("SELECT * FROM TEAMS")) {
            ResultSet rs = pst.executeQuery();
            Hashtable<Integer, String> teams = new Hashtable<>();
            while (rs.next()) {
                teams.put(rs.getInt("team_id"), rs.getString("name"));
            }
            return teams;
        }
    }
}

UI 冻结时不显示错误堆栈跟踪。我希望这些团队显示在主页上(在线程成功运行后)。请建议我哪里出错了?

【问题讨论】:

  • 也许这会有所帮助? Concurrency in JavaFX
  • “......当我切换场景并尝试切换回主页(正在获取数据的地方)时,UI 完全冻结......”因为这似乎是导致问题的原因,我建议编辑您的问题并包含执行此操作的代码。
  • minimal reproducible example 请(硬编码线程中获取的数据,根据需要休眠)..
  • 在调试器中运行它。单步执行代码。检查哪些线程被阻塞以及阻塞在哪里。
  • 感谢您的建议,问题是由于切换场景一次又一次地重新加载,创建新线程并填满数据库连接池。

标签: java javafx


【解决方案1】:

当我在 initialize 方法中启动 TeamsDAO 对象时,每次我切换回 Home 控制器时它都会创建一个新的数据库连接,因此会填满连接池。为了解决这个问题,我在 Home.java 中创建了一个静态块,并且只获取了一次我需要的数据。

更新 Home.java:

public class Home implements Initializable {

    private static TeamsDAO teamsDAO;

    @FXML
    private BorderPane borderPane;
    @FXML
    private Label cricProTitle;
    @FXML
    private Label homepageLabel;
    @FXML
    private Label banner;
    @FXML
    private GridPane buttonContainer;

    static {
        try {
            teamsDAO = new TeamsDAO();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        Task<Hashtable<Integer, String>> task = new Task<>() {
            @Override
            protected Hashtable<Integer, String> call() throws Exception {
                return teamsDAO.getTeams();
            }
        };

        task.setOnSucceeded(e -> {
            System.out.println(task.getValue());
        });

        Thread x = new Thread(task);
        x.setDaemon(true);
        x.start();
        System.out.println(x.getState());
    }

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle)  {
    //setting UI properties here..
    }

}

【讨论】:

猜你喜欢
  • 2017-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多