我想调用CompletableFuture.supplyAsync()
将阻塞任务委托给另一个线程。一旦该任务完成,我希望CompletableFuture.thenAccept
使用者在调用线程的上下文中运行。
例如:
// Thread 1
CompletableFuture.supplyAsync(() -> {
// Thread 2
return BlockingMethod();
}).thenAccept((
Object r) -> {
// Thread 1
});
以下代码表明CompletableFuture.thenAccept
在自己的线程中运行;可能与CompletableFuture.supplyAsync
相同的池,因为我在运行它时得到相同的线程ID:
System.out.println("Sync thread supply " + Thread.currentThread().getId());
CompletableFuture.supplyAsync(() -> {
System.out.println("Async thread " + Thread.currentThread().getId());
try {
Thread.sleep(2000);
}
catch (Exception e) {
e.printStackTrace();
}
return true;
}).thenAccept((
Boolean r) -> {
System.out.println("Sync thread consume " + Thread.currentThread().getId());
});
Thread.sleep(3000);
是否可以让CompletableFuture.thenAccept
与调用线程同时运行?
答案 0 :(得分:3)
CompletableFuture
只会在收件人Consumer
(由thenAccept
返回的)完成后执行CompletableFuture
注册的supplyAsync
,因为它需要它完成的价值。
如果在调用CompletableFuture
时接收器thenAccept
完成,则Consumer
将在调用线程中执行。否则,它将在完成Supplier
提交给supplyAsync
的任何线程上执行。
是否可以同时运行
CompletableFuture.thenAccept
与调用线程?
这是一个令人困惑的问题,因为一个线程一次只能运行一件事。单个线程没有并发。 Concurrently 是跨多个线程的属性。
如果您希望Consumer
在调用thenAccept
的同一线程上运行,然后在join
上运行CompletableFuture
,则阻止此线程直到将来完成。然后,您可以自己执行Consumer
或致电thenAccept
为您执行。
例如
CompletableFuture<Boolean> receiver = CompletableFuture.supplyAsync(() -> {
System.out.println("Async thread " + Thread.currentThread().getId());
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
return true;
});
receiver.join();
Consumer<Boolean> consumer = (Boolean r) -> {
System.out.println("Sync thread consume " + Thread.currentThread().getId());
};
consumer.accept(receiver.get());
(省略了异常处理。)
如果您希望Consumer
与提供给Supplier
的{{1}}并行运行,那是不可能的。 supplyAsync
意味着消耗Consumer
生成的值。 <{1}}完成后,该值才可用。
答案 1 :(得分:0)
如果我理解你的想法,你想要分配I / O密集型任务,但在“事件循环”(想想Javascript)中进行所有处理,那么你的代码可以转换为
Executor eventLoop = Executors.newSingleThreadExecutor();
Executor ioMultiplexor = Executors.newCachedThreadPool();
eventLoop.execute(() -> {
System.out.println("event loop thread supply " + Thread.currentThread().getId());
CompletableFuture.supplyAsync(() -> {
System.out.println("I/O multiplexor thread " + Thread.currentThread().getId());
try {
Thread.sleep(2000);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}, ioMultiplexor).thenAcceptAsync((Boolean r) -> {
System.out.println("event loop thread consume " + Thread.currentThread().getId());
}, eventLoop);
});
Thread.sleep(3000);
// shut down executors
打印
event loop thread supply 10
I/O multiplexor thread 11
event loop thread consume 10
如果此代码用于某些请求处理,其中可能存在许多并发请求,那么您可能希望拥有一个全局eventLoop
和一个全局ioMultiplexer
,并且您还希望释放完成将任务提交到eventLoop
后,主请求处理线程。