MMA*_*ams 5 java multithreading javafx
我正在看这个问题JavaFX showDialogue after thread task iscomplete,但我的问题有点相反。在文件选择器或警报之后需要从用户返回一些数据时,最好的线程关闭方法是什么?
这是我现在所拥有的:
Platform.runLater(()->{
File file = fileChooser.showOpenDialog(root.getScene().getWindow());
if(file == null) {
return;
}
executorService.execute(()->{
//more code here which uses file
});
});
Run Code Online (Sandbox Code Playgroud)
其中 executorService 是之前创建的 ExecutorService。我想我可以轻松地使用任务或线程或其他任何东西,但它如何线程化并不重要,只是这需要一段时间,我不希望在应用程序线程上发生,因为它会锁定 UI。
我知道这不是 mvce,但我希望它能演示我在Platform.runLater调用内的线程时遇到的问题。
这是一个极端的例子,说明了这种事情是多么复杂
@FXML
public void copyFiles(ActionEvent event){
//this method is on the application thread because a button or something started it
// so we thread off here
executorService.execute(()->{
// do some stuff
// ...
// get location to copy to from user
// must happen on the application thread!
Platform.runLater(()->{
File file = fileChooser.showOpenDialog(root.getScene().getWindow());
if(file == null) {
return;
}
executorService.execute(()->{
// more code here which uses file
// ...
// oh wait, some files have the same names!
// we need a user's confirmation before proceeding
Platform.runLater(()->{
Alert alert = new Alert(AlertType.CONFIRMATION, "Do you want to overwrite files with the same names?", ButtonType.OK, ButtonType.CANCEL);
Optional<ButtonType> choice = alert.showAndWait();
if(choice.isPresent && choice.get == ButtonType.OK){
// do something, but not on the application thread
executorService.execute(()->{
// do the last of the copying
// ...
});
}
});
});
});
});
}
Run Code Online (Sandbox Code Playgroud)
如果您需要在返回结果的 UI 线程上执行某些操作,请创建一个FutureTask,将其提交给 UI 线程,然后在后台线程上等待它完成。这允许您“扁平化”代码。
你也可以抽象Platform.runLater(...)为 an Executor(毕竟,它只是执行Runnables 的东西),这可以使它(也许)稍微干净一些。
通过分成更小的方法(通常只使用其他标准编程技术),您可以使代码变得非常干净。
这是基本思想(您需要添加异常处理,或创建一个Callable(可以抛出异常)而不是一个Runnable):
@FXML
public void copyFiles(ActionEvent event){
Executor uiExec = Platform::runLater ;
//this method is on the application thread because a button or something started it
// so we thread off here
Callable<Void> backgroundTask = () -> {
doFirstTimeConsumingThing();
FutureTask<File> getUserFile = new FutureTask<>(this::getUserFile) ;
uiExec.execute(getUserFile);
File file = getUserFile.get();
if (file == null) return null ;
doAnotherTimeConsumingThing(file);
FutureTask<Boolean> getUserConfirmation = new FutureTask<>(this::showConfirmation);
uiExec.execute(getUserConfirmation);
if (! getUserConfirmation.get()) return null ;
doMoreTimeConsumingStuff();
// etc...
return null ;
};
executorService.execute(backgroundTask);
}
private File getUserFile() {
return fileChooser.showOpenDialog(root.getScene().getWindow());
}
private Boolean getUserConfirmation() {
Alert alert = new Alert(AlertType.CONFIRMATION, "Do you want to overwrite files with the same names?", ButtonType.OK, ButtonType.CANCEL);
return alert.showAndWait()
.filter(ButtonType.OK::equals)
.isPresent();
}
private void doFirstTimeConsumingThing() {
// ...
}
private void doAnotherTimeConsumingThing(File file) {
// ....
}
private void doMoreTimeConsumingStuff() {
// ...
}
Run Code Online (Sandbox Code Playgroud)
您的问题似乎是在后台任务中需要信息,而这些信息只能在 JavaFX 应用程序线程上检索。James_D 给出的答案非常适合使用. FutureTask我想提供一种替代方案:(CompletableFuture在 Java 8 中添加)。
public void copyFiles(ActionEvent event) {
executorService.execute(() -> {
// This uses CompletableFuture.supplyAsync(Supplier, Executor)
// need file from user
File file = CompletableFuture.supplyAsync(() -> {
// show FileChooser dialog and return result
}, Platform::runLater).join(); // runs on FX thread and waits for result
if (file == null) {
return;
}
// do some stuff
// ask for confirmation
boolean confirmed = CompletableFuture.supplyAsync(() -> {
// show alert and return result
}, Platform::runLater).join(); // again, runs on FX thread and waits for result
if (confirmed) {
// do more stuff
}
});
}
Run Code Online (Sandbox Code Playgroud)
两者FutureTask都会CompletableFuture为你工作。我更喜欢CompletableFuture它,因为它提供了更多选项(如果需要),并且该join()方法不会像get()那样抛出已检查的异常。但是,CompletableFuture是 a Future(就像FutureTask),因此您仍然可以get()与 a 一起使用CompletableFuture。
| 归档时间: |
|
| 查看次数: |
1578 次 |
| 最近记录: |