【发布时间】:2015-06-02 21:10:36
【问题描述】:
我有一个库,其中我为我们的客户提供了两种方法,同步和异步。他们可以调用他们认为适合他们目的的任何方法。
- executeSynchronous() - 等到我有结果,然后返回结果。
- executeAsynchronous() - 立即返回一个 Future,如果需要,可以在其他事情完成后进行处理。
他们将传递其中包含用户 ID 的 DataKey 对象。我们将根据用户 ID 确定调用哪台机器。因此,我们将使用 AsyncRestTemplate 对 url 进行 http 调用,然后根据是否成功将响应发送回给他们。
下面是我的界面:
public interface Client {
// for synchronous
public DataResponse executeSync(final DataKey key);
// for asynchronous
public Future<DataResponse> executeAsync(final DataKey key);
}
下面是我的实现:
public class DataClient implements IClient {
// does this have to be final?
private final AsyncRestTemplate restTemplate = new AsyncRestTemplate();
@Override
public DataResponse executeSync(final DataKey keys) {
Future<DataResponse> responseFuture = executeAsync(keys);
DataResponse response = null;
try {
response = responseFuture.get(keys.getTimeout(), TimeUnit.Milliseconds);
} catch (CancellationException e) {
// what to do here?
} catch (InterruptedException e) {
// is this right way to deal with InterruptedException?
throw new RuntimeException("Interrupted", e);
} catch (ExecutionException e) {
// what do you mean by ExecutionException? And how should we deal with this?
DataLogging.logErrors(e.getCause(), DataErrorEnum.ERROR_CLIENT, keys);
response = new DataResponse(null, DataErrorEnum.ERROR_CLIENT, DataStatusEnum.ERROR);
} catch (TimeoutException e) {
DataLogging.logErrors(e.getCause(), DataErrorEnum.TIMEOUT_ON_CLIENT, keys);
response = new DataResponse(null, DataErrorEnum.TIMEOUT_ON_CLIENT, DataStatusEnum.ERROR);
}
return response;
}
@Override
public Future<DataResponse> executeAsync(final DataKey keys) {
final SettableFuture<DataResponse> responseFuture = SettableFuture.create();
restTemplate.exchange(createURL(keys), HttpMethod.GET, keys.getEntity(), String.class).addCallback(
new ListenableFutureCallback<ResponseEntity<String>>() {
@Override
public void onSuccess(ResponseEntity<String> result) {
responseFuture.set(new DataResponse(result.getBody(), DataErrorEnum.OK,
DataStatusEnum.SUCCESS));
}
@Override
public void onFailure(Throwable ex) {
DataLogging.logErrors(ex, DataErrorEnum.ERROR_SERVER, keys);
responseFuture.set(new DataResponse(null, DataErrorEnum.ERROR_CLIENT,
DataStatusEnum.ERROR));
}
});
return responseFuture;
}
}
现在我的问题是:
- 如何正确处理
executeSync的catch块中的异常? CancellationException 和 TimeoutException 有什么区别吗?还有我们应该如何处理ExecutionException? - 我的 DataKey 在我的界面中是否必须是最终的?如果我在 executeAsync 实现中删除最终变量,则会收到编译错误
Cannot refer to a non-final variable keys inside an inner class defined in a different method。 - 这是在我的
executeAsync方法中使用 ListenableFutureCallback 的正确方法吗?或者有没有更好的使用方法?
对于我的同步和异步实现的设计,也欢迎任何输入/建议。
【问题讨论】:
标签: java multithreading asynchronous guava future