假设我有这段代码:
public HttpResponse myFunction(...) {
final HttpResponse resp;
OnResponseCallback myCallback = new OnResponseCallback() {
public void onResponseReceived(HttpResponse response) {
resp = response;
}
};
// launch operation, result will be returned to myCallback.onResponseReceived()
// wait on a CountDownLatch until operation is finished
return resp;
}
显然我无法从onResponseReceived为resp赋值,因为它是最终变量,但如果它不是最终变量onResponseReceived则看不到它。 那么,如何从onResponseReceived?
为resp赋值我想要创建一个用于封装resp对象的包装类。最后一个对象将是这个包装类的一个实例,我可以将值赋给resp处理最终类中的对象(这不是最终的)。
代码就是这个:
class ResponseWrapper {
HttpResponse resp = null;
}
public HttpResponse myFunction(...) {
final ResponseWrapper respWrap = new ResponseWrapper();
OnResponseCallback myCallback = new OnResponseCallback() {
public void onResponseReceived(HttpResponse response) {
respWrap.resp = response;
}
};
// launch operation, result will be returned to myCallback.onResponseReceived()
// wait on a CountDownLatch until operation is finished
return respWrap.resp;
}
您对此解决方案有何看法?
答案 0 :(得分:7)
java.util.concurrent.atomic.AtomicReference
标准做法是使用最终的AtomicReference,您可以设置和获取。这也增加了线程安全的好处:)正如您所提到的,CountDownLatch有助于等待完成。
答案 1 :(得分:4)
您的解决方案与其他解决方案一样有效。其他流行的选择包括单元素数组
final HttpResponse[] resp = new Response[1];
// In the callback
resp[0] = response;
// After the operation
return resp[0];
和通用包装
public class Ref<T> {
public T value;
}
final Ref<HttpResponse> resp;
// In the callback
resp.value = response;
// After the operation
return resp.value;
答案 2 :(得分:1)
您可以使用SynchronousQueue
将备忘和等待合并为一个(省略异常处理)
public HttpResponse myFunction(...) {
final Queue<HttpResponse> resp = new SynchronousQueue<HttpResponse>();
OnResponseCallback myCallback = new OnResponseCallback() {
public void onResponseReceived(HttpResponse response) {
resp.put(response);
}
};
return resp.take();
}
答案 3 :(得分:0)
我要做的改变是使用AtomicReference,因为这显然是多线程的,你不必编写自己的包装器。否则,对我来说似乎很合理。
答案 4 :(得分:0)
你可以使它变为可变和最终;)最简单的方法是使用na数组,但也可以使用AtomicReference。
public HttpResponse myFunction(...) {
final HttpResponse[] resp = { null };
OnResponseCallback myCallback = new OnResponseCallback() {
public void onResponseReceived(HttpResponse response) {
resp[0] = response;
}
};
// launch operation, result will be returned to myCallback.onResponseReceived()
// wait on a CountDownLatch as soon as operation is finished
return resp[0];
}
或
public HttpResponse myFunction(...) {
final AtomicReference<HttpResponse> resp = new AtomicReference<HttpResponse>();
OnResponseCallback myCallback = new OnResponseCallback() {
public void onResponseReceived(HttpResponse response) {
resp.set(response);
}
};
// launch operation, result will be returned to myCallback.onResponseReceived()
// wait on a CountDownLatch as soon as operation is finished
return resp.get();
}