这是我的JavaFX控制器
public class MainController {
private Future<Graph> operation;
private ExecutorService executor = Executors.newSingleThreadExecutor();
@FXML
private void createSession() { //invoked by a button click in the view
//GraphCreationSession implements Callable<Graph>
GraphCreationSession graphSession = new GraphCreationSession();
if (operation != null && !operation.isDone()) {
//cancel previous session
operation.cancel(true);
}
operation = executor.submit(graphSession);
???
}
}
所以我的问题是,在javaFX上下文中处理Future
的结果的成语是什么?
我知道我可以做operation.get()
并且线程将阻塞直到操作完成,但我将阻止Application线程。我在Callable
完成后发现了一个回调,我发现了CompletableFuture
,这种做法是通过 thenAccept 进行的,但基于{{{ 3}}线程仍然会被阻止,这会破坏未来的点,就像答案所提到的那样。
在我的特定情况下,Callable的结果(我的示例中的图形)包含我希望在操作完成时在面板中显示的结果。
答案 0 :(得分:3)
最简单的方法是更改GraphCreationSession
,使其成为Task<Graph>
的子类,而不是Callable<Graph>
的实现:
public class GraphCreationSession extends Task<Graph> {
@Override
public Graph call() throws Exception {
// implementation as before...
}
}
然后你可以做
public class MainController {
private ExecutorService executor = Executors.newSingleThreadExecutor();
private GraphCreationSession graphSession ;
@FXML
private void createSession() { //invoked by a button click in the view
if (graphSession != null && !graphSession.getState()==Worker.State.RUNNING) {
//cancel previous session
graphSession.cancel(true);
}
graphSession = new GraphCreationSession();
graphSession.setOnSucceeded(event -> {
Graph graph = graphSession.getValue();
// update UI...
});
executor.execute(graphSession);
}
}
如果您无法更改GraphCreationSession
,或者希望它独立于javafx API,那么只需将其包装在一个简单的Task
实现中:
public class MainController {
private Task<Graph> graphSession ;
// ...
@FXML
public void createSession() {
// ...
graphSession = new Task<Graph>() {
@Override
public Graph call() throws Exception {
return new GraphCreationSession().call();
}
};
graphSession.setOnSucceeded(...);
executor.execute(graphSession);
}
}