Вы никогда не должны запускать долго выполняющиеся задачи в Потоке приложений JavaFX .Это будет препятствовать тому, чтобы упомянутый поток делал любые вещи, связанные с GUI, которые приводят к замороженному пользовательскому интерфейсу.Это делает вашего пользователя (ей) грустным.Тем не менее, ваша попытка поставить долгосрочную задачу на фоновую задачу ошибочна.Вы вызываете Thread.join
, который блокирует вызывающий поток до тех пор, пока целевой поток не умрет;фактически это то же самое, что просто запустить задачу в вызывающем потоке.
Для быстрого исправления вашего примера вы можете сделать следующее:
@FXML
private void test(){
textField.setText("Pending...");
Thread t = new Thread(){
@Override public void run(){
boolean passed = doStuff();
Platform.runLater(() -> {
if(passed){
textField.setText("OK");
} else {
textField.setText("Error");
}
});
}
};
t.start();
}
Это создаст поток, запустите его и дайте ему поработать в фоновом режиме, а Поток приложений JavaFX продолжит делать то, что ему нужно.Внутри фонового потока вы должны обновить TextField
внутри Platform.runLater(Runnable)
вызова.Это необходимо, потому что вы никогда не должны обновлять живой граф сцены из потока, отличного от потока приложения JavaFX ;это приведет к неопределенному поведению.Кроме того, вы должны изучить «реализует Runnable» против «расширяет поток» в Java .Лучше или, по крайней мере, более идиоматично сделать:
Thread t = new Thread(() -> { /* background code */ });
Вы также можете использовать javafx.concurrent.Task
, который может упростить связь с приложением JavaFX.тема .Один из вариантов:
@FXML
private void test(){
textField.setText("Pending...");
Task<Boolean> task = new Task<>() {
@Override protected Boolean call() throws Exception {
return doStuff();
}
};
task.setOnSucceeded(event -> textField.setText(task.getValue() ? "Ok" : "Error"));
new Thread(task).start();
}
Вы также можете привязать TextField
к message
свойству Task
и вызвать updateMessage("Pending...")
внутри метода call
.Вы можете даже предоставить более подробные сообщения, если и когда это возможно.
Тем не менее, создание и запуск Thread
s сами по себе не идеальны, и вам следует изучить пул потоков (используя что-то вродеExecutorService
).Вы также можете обратиться к javafx.concurrent.Service
для повторного использования Task
с.
Для получения дополнительной информации о параллелизме JavaFX см. Параллельность в JavaFX и прочитайте документацию классов в javafx.concurrent
.Для ознакомления с основами многопоточности в Java см. Урок: параллелизм из Учебные руководства Java ™ .