亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java/JavaFX:輪詢數據庫以進行單值更新,同時保持 GUI 中的響應能力

Java/JavaFX:輪詢數據庫以進行單值更新,同時保持 GUI 中的響應能力

烙印99 2022-09-21 16:42:51
我和一些朋友一起,試圖創建一個回合制游戲。我們在檢查用戶何時輪到他們時遇到了一些問題,同時保持GUI的響應性,以及在游戲關閉時關閉我們現在使用的線程。我希望獲得有關如何執行此操作的一些信息,但我不確定問題是與JavaFX相關,還是與線程相關,還是兩者兼而有之。我試圖盡可能多地搜索,但根本找不到我想要的東西,即使我相信它很簡單。現在,我們有一個線程運行一個循環,當你點擊一個按鈕來檢查它是否輪到你了。當輪到你時,我們希望禁用一些用戶輸入,所以我不確定我們是否真的需要一個線程,除了保持響應能力。我也嘗試過實現一個擴展 Thread 的類,但這似乎只會讓問題變得更糟,因為每次玩家沒有輪到它時都會啟動一個新線程,或者如果我將循環放在線程之外,則會凍結 GUI。public void refreshButtonPressed(){    try{        refreshButton.setDisable(true);        Thread pollThread = new Thread(() -> {            System.out.println("Thread started");  //Stop being able to start more threads            int user_id = 0;            String gamePin = "xxxxxx";        while (!GameConnection.yourTurn(user_id, Context.getContext().getGamePin())){ //This method checks the database if it is your turn            try{                Thread.sleep(5000);  //So we don't flood the database            }            catch (InterruptedException e){                System.out.println("Interrupted");                break;            }             //If we close the game, stop the thread/while loop.             if (TurnPolling.closedGame){                break;            }        }        playerButton.setDisable(false);        refreshButton.setDisable(false);        refreshButton.setText("Refresh");        System.out.println("Thread ended");        });        pollThread.start();    }catch (Exception e){        e.printStackTrace();    }}在游戲屏幕.fxml文件的控制器中(不是主屏幕,而是通過登錄屏幕和主擴展應用程序加載的屏幕)。public void initialize(URL location, ResourceBundle resources) {    playerButton.setDisable(!GameConnection.yourTurn(user_id, gameTurn));    myStage.setOnCloseRequest(event -> TurnPolling.closedGame = true);}目前,TurnPolling 類只有公共靜態布爾封閉游戲,以免將其保留在控制器中。最后一行設置封閉游戲 = true 實際上給了我一個空點器例外,這可能是因為舞臺尚未初始化,當我在 initialize() 方法中執行此操作時?我希望僅在輪到玩家時啟用玩家按鈕,并在游戲屏幕關閉時關閉線程(如果需要)。現在,你必須點擊一個按鈕來檢查它是否輪到你了,每五秒鐘再次檢查一次,當你關閉游戲時,它不會停止。請告訴我,如果你需要更多的代碼或澄清,這是我的第一個大項目,所以我真的不知道放多少在這里。我知道這不是有效的代碼,但它是我能做的,而不會讓它感覺像是混亂。感謝您的回答!
查看完整描述

1 回答

?
犯罪嫌疑人X

TA貢獻2080條經驗 獲得超4個贊

首先,重要的是要記住,不允許在 JavaFX 應用程序線程以外的任何線程中更改 JavaFX 節點。因此,您的線程需要移動以下行:


playerButton.setDisable(false);

refreshButton.setDisable(false);

refreshButton.setText("Refresh");

到一個可運行的,它被傳遞給平臺。


Platform.runLater(() -> {

    playerButton.setDisable(false);

    refreshButton.setDisable(false);

    refreshButton.setText("Refresh");

});

請注意,對一個線程中的字段所做的更改在另一個線程中可能不可見,除非聲明為 。從 Java 語言規范:TurnPolling.closedGamevolatile


例如,在下面的(損壞的)代碼片段中,假定這是一個非字段:this.donevolatileboolean


while (!this.done)

    Thread.sleep(1000);

編譯器可以自由地讀取該字段一次,并在每次執行循環時重用緩存的值。這意味著循環永遠不會終止,即使另一個線程更改了 的值。this.donethis.done


使用任務和服務

JavaFX為所有這些提供了一個更干凈的解決方案:任務和服務。


服務創建任務。服務具有可綁定的值屬性,該屬性始終等于最近創建的任務的值。您可以將按鈕屬性綁定到服務的值屬性:


int user_id = 0;


Service<Boolean> turnPollService = new Service<Boolean>() {

    @Override

    protected Task<Boolean> createTask() {

        return new Task<Boolean>() {

            @Override

            protected Boolean call()

            throws InterruptedException {


                updateValue(true);


                String gamePin = Context.getContext().getGamePin();


                while (!GameConnection.yourTurn(user_id, gamePin)) {

                    Thread.sleep(5000);


                    if (TurnPolling.closedGame){

                        break;

                    }

                }


                return false;

            }

        };

    }

};


playerButton.disableProperty().bind(turnPollService.valueProperty());

refreshButton.disableProperty().bind(turnPollService.valueProperty());


refreshButton.textProperty().bind(

    Bindings.when(

        turnPollService.valueProperty().isEqualTo(true))

        .then("Waiting for your turn\u2026")

        .otherwise("Refresh"));

當玩家的回合完成時,您將調用 。turnPollService.restart();


無論您是使用服務,還是僅使用 Platform.runLater,您仍然需要通過創建它或將所有對它的訪問包含在塊(或鎖保護)中來使線程安全。TurnPolling.closedGamevolatilesynchronized


查看完整回答
反對 回復 2022-09-21
  • 1 回答
  • 0 關注
  • 395 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號