首先,我决定让我的类阻塞(让消费者更容易使用——但对我来说可能写起来更乏味)。与让消费者定义异步回调相反。这是一个好的设计模式吗?这样,用户可以获得预期的行为,但如果他们对线程的阻塞时间不满意,则可以实现自己的多线程。
我有一个构造函数,它根据异步回调的结果在类中设置最终字段:
class Example {
private final int x;
Example(){
asyncFunc(/* callback */ result -> x = result)
}
}
这不起作用,所以我使用了原子引用,并实现了一个阻塞循环,直到返回结果,如下所示:
class Example {
private final int x;
Example(){
x = waitAsyncFunc();
}
private int waitAsyncFunc(){
AtomicBoolean finished = new AtomicBoolean(false);
AtomicReference<byte[]> result = new AtomicReference<>();
asyncFunc(result -> {
result .set(res);
finished.set(true);
});
while (!finished.get()) { /* No op */ }
return result.get();
}
}
这是阻止/检索结果的好方法吗?
最简单的解决方案是
class Example {
private final int x;
Example() {
CompletableFuture<Integer> f = new CompletableFuture();
asyncFunc(f::complete);
x = f.join();
}
}
但请考虑在构建
Example
实例之前等待异步作业完成的替代方案。
您可以使用 CountDownLatch,而不是用循环阻塞线程。
取自文档(https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)
一种同步辅助工具,允许一个或多个线程等待,直到其他线程中执行的一组操作完成。
你的代码看起来像这样:
private int waitAsyncFunc() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<byte[]> result = new AtomicReference<>();
asyncFunc(result -> {
result.set(res);
latch.countDown();
});
latch.await(); //You can even specify a timeout
return result.get();
}