假设我有一个具有并行度n的ForkJoinPool设置,并且我调用这样的并行计算:
workpool.submit(
() -> {
objects.values().parallelStream().forEach(obj -> {
obj.foo();
});
});
我这样做是为了确保在那里产生的线程在工作池中创建(我有不同的系统组件需要隔离)。现在假设调用它的线程也在这个工作池内执行,我做:
Future<?> wait = workpool.submit(
() -> {
objects.values().parallelStream().forEach(obj -> {
obj.foo();
});
});
wait.get()
1)我是否阻止了ForkJoinPool中的线程?如果我在期货中有n个线程全部阻止,而在尝试在工作池中安排任务时,这是否会导致死锁?我不清楚ForkJoinPool中的“最大并行度”是否意味着(如果有n个非阻塞任务),总会有n个线程在执行,或者是否有固定数量的线程,无论是否有阻止。如果我使用wait.join()代替wait.join
会怎样(我不需要检查异常,因为此代码中抛出的任何异常都会产生runtimeexception。如果我理解正确,join()将允许线程执行排队等待时的任务)
2)如果我通过执行() - &gt;创建一个可运行的“包装器”类,我仍然可以获得并行流的轻量级forkjoin任务的好处。 {}
3)使用它是否有任何缺点/好处(假设.join()确实实现了我认为它的工作窃取行为):
CompletableFuture.supplyAsync(this::mylambdafunction, workpool)
.thenAccept(this::mynextfunction);
答案 0 :(得分:1)
对第1点的回应:很难知道您的代码是否会在没有看到实际方法实现的情况下阻塞。处理阻塞代码的一种方法是增加forkjoin线程池中的线程数。通常,forkjoin线程中的线程数为n + 1,用于计算密集型任务,其中n =处理器数。或者,如果您有I / O阻止,则可以使用ManagedBlocker。
对第2点的回应:是
第3点的响应:您的completableFuture代码的明显优势在于thenAccept是非阻塞的。因此,控件将立即通过您的CompletableFuture块到下一个语句而不等待,而在您使用ForkJoin池编写的早期代码中,wait.get()将阻塞,直到您获得答案,并且在此之前不会继续。