我正在使用ScheduledService来确保在应用程序打开时服务器连接保持活动状态,并且用户没有主动与应用程序交互。
有些时候应用程序线程在应用程序关闭时没有结束,我假设它可能是导致我的问题的ScheduledService。
由于我的应用程序将包含多个阶段,因此我无法在窗口关闭时停止服务。有没有其他方法可以在线程执行期间查看某个阶段当前是否已打开,是否取消该服务?
//Service set up
service = new KeepSessionAliveService() ;
service.setPeriod(Duration.minutes(REPEAT_PERIOD));
service.setDelay(Duration.minutes(INITIAL_DELAY));
service.start();
private class KeepSessionAliveService extends ScheduledService<Void> {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws ClientProtocolException, IOException {
pingServerToKeepAlive();
return null;
}
};
}
}
如果这不是最好的处理方式,我愿意接受建议。
感谢。
编辑: 我试图提供服务器访问的默认实现,其中开发人员只需调用提供所需的预期类定义的包装器方法。调用调用时,它将在进程运行时提供进度警报,然后在完成后关闭它。最初我尝试了一项服务,但似乎无法让它工作,因此建议尝试以下方法:
public <T> void executeServerCall(ServiceRequest serviceRequest, String message, Stage stage, Class<T> valueType, Consumer<T> success, Consumer<Exception> failure) {
Alert progressAlert = displayProgressDialog(message, stage);
Executors.newSingleThreadExecutor().execute(() -> {
try {
T result = executeServerCall(serviceRequest, valueType);
Platform.runLater(() ->
{
forcefullyHideDialog(progressAlert);
success.accept(result);
});
} catch (Exception e) {
Platform.runLater(() ->
{
forcefullyHideDialog(progressAlert);
failure.accept(e);
});
}
});
}
根据您的回复,我确实证明正是这段代码正在运行应用程序线程,而不是服务。如果我能在这一点上完成我所需要的服务,我会非常乐意改变它。但是我找不到办法来做到以下几点:
public <T> void executeServerCall(ServiceRequest serviceRequest, String message, Stage stage, Class<T> valueType, Consumer<T> success, Consumer<Exception> failure) {
Service<valueType> service = ....
答案 0 :(得分:1)
您正在创建许多单线程执行程序,您在其上执行对服务器的每个单独调用。每个执行程序都创建自己的非守护程序线程,然后等待下一个runnable执行。
如果所有这些对服务器的调用都应该发生在一个线程上,那么你应该创建一个执行器来执行此操作。 (实际上,如果你希望它们发生在多个线程上,你仍然应该创建一个执行器,只使用多个线程,而不是一个线程。)
所以:
private final ExcecutorService serverCallExec = Executors.newSingleThreadedExecutor();
// ...
public <T> void executeServerCall(ServiceRequest serviceRequest, String message, Stage stage, Class<T> valueType, Consumer<T> success, Consumer<Exception> failure) {
Alert progressAlert = displayProgressDialog(message, stage);
serverCallExec.execute(() -> {
try {
T result = executeServerCall(serviceRequest, valueType);
Platform.runLater(() ->
{
forcefullyHideDialog(progressAlert);
success.accept(result);
});
} catch (Exception e) {
Platform.runLater(() ->
{
forcefullyHideDialog(progressAlert);
failure.accept(e);
});
}
});
}
要让执行程序在应用程序关闭时终止其线程,请安排从serverCallExec.shutdown();
方法调用Application.stop()
,或者通过指定线程工厂使执行程序使用的线程成为守护程序线程:
private final ExecutorService serverCallExec = Executors.newSingleThreadedExecutor((Runnable r) -> {
Thread t = new Thread(r);
t.setDaemon(true);
return t ;
});
答案 1 :(得分:0)
感谢您的建议 当我们来回走动时,我尝试了这个。
public <T> void executeServerCall(ServiceRequest serviceRequest, String message, Stage stage, Class<T> valueType, Consumer<T> success, Consumer<Throwable> failure) {
Service<T> service = new Service<T>(){
@Override
protected Task<T> createTask() {
return new Task<T>() {
@Override
protected T call() throws Exception {
return executeServerCall(serviceRequest, valueType);
}
};
}
};
service.setOnSucceeded(event -> success.accept(service.getValue()));
service.setOnFailed(event -> failure.accept(service.getException()));
ProgressDialog pd = new ProgressDialog(service);
pd.setContentText(message);
pd.initModality(Modality.WINDOW_MODAL);
pd.initOwner(stage);
service.start();
}
这解决了我的问题并使用并发服务来处理我的问题。我不确定为什么以前这不起作用(我可能在创建服务时有一些奇怪的设置)。
这是一个更好的解决方案,你上面发布的那个我的需求?我只想抽象出呼叫的管道。这似乎是这样做的。