Assuming that I have a ForkJoinPool setup with degree of parallelism n, and that I call a parallel computation like this:
workpool.submit(
() -> {
objects.values().parallelStream().forEach(obj -> {
obj.foo();
});
});
I do this to ensure that the threads spawned there are created inside the workpool (I have different components of the system that need to be isolated). Now assume that the thread in which this is called, is also executing inside this workpool, and I do:
Future<?> wait = workpool.submit(
() -> {
objects.values().parallelStream().forEach(obj -> {
obj.foo();
});
});
wait.get()
1) Am I blocking a thread in the ForkJoinPool? If I were to have n threads all block on futures, while trying to schedule a task in the workpool, would this lead to deadlock? It's not clear to me whether the "maximum degree of parallellism" in the ForkJoinPool means that (if there are n non-blocked tasks), there will always be n threads executing, or whether there is a fixed number of threads,regardless of whether there are blocked. What if I use wait.join() insteadwait.join
instead (I do not need checked exceptions as any exception thrown in this code will already generate a runtimeexception. If I understand correctly, join() will allow threads to execute queued tasks while waiting)
2) Am I still getting the benefit of the light-weight forkjoin tasks of the parallel stream if I am creating a runnable "wrapper" class by doing () -> {}
3) Is there any downside/upside to using this instead (assuming that the .join() does indeed implement the work-stealing behaviour that I think it does):
CompletableFuture.supplyAsync(this::mylambdafunction, workpool)
.thenAccept(this::mynextfunction);
Response to point 1: It's difficult to know whether your code will block without seeing the actual method implementations. One approach to dealing with blocking code is to increase the number of threads in the forkjoin threadpool. Normally, the number of threads in a forkjoin thread is n+1 for compute intensive tasks where n=number of processors. Or if you have I/O blocking you could use a ManagedBlocker.
Response to point 2: Yes
Response for point 3: The obvious upside to your completableFuture code is that the thenAccept is non blocking. So control will immediately go past your CompletableFuture block to the next statement without waiting whereas in the earlier code you wrote with a ForkJoin pool the wait.get() will block till you obtain an answer and won't proceed till then.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With