如何将阻塞方法调用“转换”为CompletableFuture?示例:
T waitForResult() throws InterruptedException {
obj.await(); // blocking call
// ...
return something;
}
我需要把它变成这样:
CompletableFuture.of(this::waitForResult); // .of(Callable<T>) doesn't exist
要考虑的一些事情:
waitForResult()
可能会引发异常。必须正确处理这些内容,以便completableFuture.get()
会抛出InterruptedException
或ExecutionException
。supplyAsync()
会这样做)。我尝试过此操作,但这无法正确处理异常:
CompletableFuture.completedFuture(Void.TYPE).thenApply(v -> {
try {
listener.await();
// ...
return listener.getResult();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (SnmpException e) {
throw new RuntimeException(e);
}
});
我认识Create CompletableFuture from a sync method call,但这对我没有帮助:
答案 0 :(得分:1)
您可以尝试这样做,因为它严重滥用了CompletableFuture,但您必须确定其是否适合您的用例:
private static <T> CompletableFuture<T> supplySynchronously(Callable<T> callable) {
CompletableFuture<T> f = new CompletableFuture() {
public T get() throws InterruptedException, ExecutionException {
synchronized (callable) {
if (!isDone()) {
try {
T result = callable.call();
complete(result);
} catch (Exception e) {
completeExceptionally(e);
}
}
}
return (T) super.get();
}
};
return f;
}
答案 1 :(得分:1)
让方法Listener.await()
调用方法CountDownLatch.await()
:
class Listener {
CountDownLatch latch = new CountDownLatch(counter);
void someMethod(){
latch.countdown();
}
public void await() {
latch.await();
}
}
然后您可以通过以下方式将其转换为异步方式:
class Listener {
AsynCountDownLatch latch = new AsynCountDownLatch(counter);
void someMethod(){ // here nothing changed
latch.countdown();
}
public CompletableFuture<Void> async() {
return latch.fin;
}
}
class AsynCountDownLatch extends AsynCountDownLatch {
CompletableFuture<Void> fin = new CompletableFuture<>();
public AsynCountDownLatch(long counter) {
super(counter);
}
public void countdown() {
super.countdown();
if (super.getCount()==0L) {
fin.complete(null);
}
}
}
UPDT:如果侦听器使用另一个类,则也必须修改/扩展/替换该类,以将阻塞操作转换为非阻塞操作。没有通用的方法可以进行这种转换。
答案 2 :(得分:0)
我不确定我是否理解您的要求。这满足他们吗?
private <T> CompletableFuture<T> supplySynchronously(Callable<T> callable) {
CompletableFuture<T> f = new CompletableFuture<>();
try {
f.complete(callable.call());
} catch (Exception e) {
f.completeExceptionally(e);
}
return f;
}