ForkJoinPool和Future.Get

use*_*513 6 java asynchronous java-8 forkjoinpool

假设我有一个具有并行度n的ForkJoinPool设置,并且我调用这样的并行计算:

 workpool.submit(
            () -> {
                    objects.values().parallelStream().forEach(obj -> {
                        obj.foo();
                    });
                });
Run Code Online (Sandbox Code Playgroud)

我这样做是为了确保在那里生成的线程在工作池中创建(我有需要隔离的系统的不同组件).现在假设调用它的线程也在这个工作池中执行,我这样做:

 Future<?> wait =  workpool.submit(
            () -> {
                    objects.values().parallelStream().forEach(obj -> {
                        obj.foo();
                    });
                });
 wait.get()
Run Code Online (Sandbox Code Playgroud)

1)我是否阻止了ForkJoinPool中的线程?如果我在期货中有n个线程全部阻止,而在尝试在工作池中安排任务时,这是否会导致死锁?我不清楚ForkJoinPool中的"最大并行度"是否意味着(如果有n个非阻塞任务),总会有n个线程在执行,或者是否有固定数量的线程,无论是否有阻止.如果我使用wait.join()代替wait.join(我不需要检查异常,因为此代码中抛出的任何异常都会生成runtimeexception.如果我理解正确,join()将允许线程在等待时执行排队的任务)

2)如果我通过执行() - > {}创建一个可运行的"包装器"类,我仍然可以获得并行流的轻量级forkjoin任务的好处

3)使用它是否有任何缺点/好处(假设.join()确实实现了我认为它的工作窃取行为):

        CompletableFuture.supplyAsync(this::mylambdafunction, workpool)  
             .thenAccept(this::mynextfunction);
Run Code Online (Sandbox Code Playgroud)

小智 1

对第 1 点的回应:在不查看实际方法实现的情况下,很难知道您的代码是否会阻塞。处理阻塞代码的一种方法是增加 forkjoin 线程池中的线程数量。通常,对于计算密集型任务,forkjoin 线程中的线程数为 n+1,其中 n=处理器数。或者,如果您有 I/O 阻塞,则可以使用 ManagedBlocker。

对第 2 点的回应:

对第 3 点的回应: completableFuture 代码的明显优点是 thenAccept 是非阻塞的。因此,控制将立即通过 CompletableFuture 块到达下一条语句,而无需等待,而在您使用 ForkJoin 池编写的早期代码中, wait.get() 将阻塞,直到您获得答案为止,并且在此之前不会继续。