[英]Running CompletableFuture.thenAccept from the calling thread?
I want to call CompletableFuture.supplyAsync()
to delegate a blocking task to another thread.我想调用
CompletableFuture.supplyAsync()
将阻塞任务委托给另一个线程。 Once that task completes I would like for the CompletableFuture.thenAccept
consumer to run in the context of the calling thread.一旦该任务完成,我希望
CompletableFuture.thenAccept
使用者在调用线程的上下文中运行。
For example:例如:
// Thread 1
CompletableFuture.supplyAsync(() -> {
// Thread 2
return BlockingMethod();
}).thenAccept((
Object r) -> {
// Thread 1
});
The following code suggests that CompletableFuture.thenAccept
runs in its own thread;下面的代码表明
CompletableFuture.thenAccept
在它自己的线程中运行; probably the same pool as CompletableFuture.supplyAsync
as I get the same thread ID when I run it:可能与
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);
Is it possible to have CompletableFuture.thenAccept
run concurrently with the calling thread?是否可以让
CompletableFuture.thenAccept
与调用线程同时运行?
The CompletableFuture
will only execute the Consumer
you register with thenAccept
when the receiver CompletableFuture
(one returned by supplyAsync
) is completed, since it needs the value it was completed with. CompletableFuture
只会在接收器CompletableFuture
(由supplyAsync
返回的supplyAsync
)完成时执行您向thenAccept
注册的Consumer
,因为它需要完成它的值。
If the receiver CompletableFuture
is complete when thenAccept
is invoked, then the Consumer
will be executed in the calling thread.如果调用
thenAccept
时接收器CompletableFuture
完成,则Consumer
将在调用线程中执行。 Otherwise, it will execute on whatever thread completes the Supplier
submitted to supplyAsync
.否则,它将在完成提交给
supplyAsync
的Supplier
任何线程上执行。
Is it possible to have
CompletableFuture.thenAccept
run concurrently with the calling thread?是否可以让
CompletableFuture.thenAccept
与调用线程同时运行?
This is a confusing question because a thread can only run one thing at a time.这是一个令人困惑的问题,因为一个线程一次只能运行一件事。 There's no concurrently for a single thread.
单个线程没有并发。 Concurrently is a property that spans multiple threads.
Concurrently是一个跨越多个线程的属性。
If you want the Consumer
to run on the same thread that invoked thenAccept
, then join
on the CompletableFuture
, blocking this thread until the future is completed.如果您希望
Consumer
在调用thenAccept
的同一线程上运行,则join
CompletableFuture
,阻塞该线程直到未来完成。 You can then execute the Consumer
yourself or call thenAccept
to execute it for you.然后您可以自己执行
Consumer
或调用thenAccept
为您执行它。
For example例如
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());
(Exception handling omitted.) (省略异常处理。)
If you want the Consumer
to run in parallel with the Supplier
supplied to supplyAsync
, that's not possible.如果您希望
Consumer
与提供给supplyAsync
的Supplier
并行运行,那是不可能的。 That Consumer
is meant to consume the value produced by the Supplier
.该
Consumer
旨在消耗Supplier
产生的价值。 That value isn't available until the Supplier
is finished.在
Supplier
完成之前,该值不可用。
If I understand your idea right that you want to fork I/O-intensive tasks but do all processing in the "event loop" (think Javascript), then your code could be translated to如果我理解你的想法是正确的,你想要分叉 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
This prints这打印
event loop thread supply 10
I/O multiplexor thread 11
event loop thread consume 10
If this code is used for some request handling where there can be many concurrent requests, you would probably want to have one global eventLoop
and one global ioMultiplexer
, and you would also want to release the main request handling thread once it finishes submitting the task onto eventLoop
.如果此代码用于某些可能有许多并发请求的请求处理,您可能希望拥有一个全局
eventLoop
和一个全局ioMultiplexer
,并且您还希望在完成提交任务后释放主请求处理线程eventLoop
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.