1

假设我有这个代码:

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 对象。最终对象将是这个包装类的一个实例,我可以将值分配给在最终类(不是最终的)内的对象上工作。

代码将是这个:

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;
}

您如何看待这个解决方案?

4

5 回答 5

7

java.util.concurrent.atomic.AtomicReference

标准做法是使用最终的 AtomicReference,您可以设置和获取它。这也增加了线程安全的好处 :) 正如您所提到的,CountDownLatch 有助于等待完成。

于 2012-12-12T17:28:06.017 回答
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;
于 2012-12-12T17:29:52.680 回答
1

您可以使用 a 将 hand-back 和 wait 合二为一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();
}
于 2012-12-12T17:36:19.787 回答
0

我要做的改变是使用AtomicReference,因为这显然是多线程的,您不必编写自己的包装器。否则,对我来说似乎是合理的。

于 2012-12-12T17:29:26.493 回答
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();
}
于 2012-12-12T17:30:47.350 回答