等待异步回调完成并传递值

时间:2018-06-05 11:49:28

标签: java asynchronous concurrency java.util.concurrent

我有以下代码段:

private ValContainer<CompletableFuture<String>> valContainer = new ValContainer<>();

public void fetchAsync(final String attrName) {

        QueryAsyncCallback asyncCallback = new QueryAsyncCallback() {
            @Override
            public void onSuccess(Message response) {
                final Data value = response.results().get("value");
                String text = value.toString();
                CompletableFuture<String> result = CompletableFuture.completedFuture(text);
                valContainer.setVal(result);
            }

            @Override
            public void onError(CallbackError error) {
                LOG.info("Error occurred");
            }

            @Override
            public void onTimeout() {
                LOG.info("Timeout occurred");
            }
        };

        Message request = new Messsage("com.example.val", "local", 0, "fetch");
        request.parameters().put("name", attrName);

        MsgOptions options = new MsgOptions(5000);
        try {
            queue.query(request, options, asyncCallback);
        } catch (QueueAccessException e) {
            e.printStackTrace();
        }
    }

现在,我可以在onSuccess()回调中轻松获取我查询的值。 ValContainer只是一个通用容器,因此我可以将值保存在匿名类中。不幸的是,在Main函数中我试图访问这个valContainer,但遗憾的是,这是异步查询,我得到NullPointerException。

...
((JavaServiceImpl) javaService).fetchAsync("test");
System.out.println("inMain value: " + ((JavaServiceImpl) javaService).getValContainer().getVal().get()); <-- this is going to be NullPointerException
...

然后在100ms后我得到了onSuccess()方法中的值。这里基本上做Thread.sleep(100)就足以获得我希望获得的值,但我真的不想阻止该线程。有没有办法以整洁的方式做到这一点?

1 个答案:

答案 0 :(得分:1)

请勿将val取消初始化ValContainer。将其初始化为new CompletableFuture<>()

private ValContainer<CompletableFuture<String>> valContainer = new ValContainer<>(new CompletableFuture<>());


public class ValContainer<T> {
    T val;

    public ValContainer(T val) {
        this.val = val;
    }
}

然后将onSuccess方法更改为

String text = value.toString(); 
valContainer.getVal().complete(text);

您无需在CompletableFuture方法中创建onSuccess

有了这个,[..]getValContainer().getVal().get()阻止,直到将来完成。