Javafx UI 在运行任务后没有响应

Javafx UI not responding after it runs Task

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

当我第一次启动应用程序时,数据已成功获取并显示在我的控制台上,但是当我切换场景并尝试切换回主页(正在获取数据的地方)时,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 冻结时不显示错误堆栈跟踪。我希望这些团队显示在主页上(在线程成功运行后)。请指出我哪里出错了?

当我在 initialize 方法中启动 TeamsDAO 对象时,每次我切换回主控制器时它都会创建一个新的数据库连接,因此会填满连接池。为了解决这个问题,我在 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..
    }

}