If the Thread inside the ForkJoinPool does a blocking I/O activity ( simulated below in code using Thread.sleep(10000)
) , it should pick up another task which is not causing blocking IO.
However, running below code with parallelism of 1 or 2 with ForkJoinPool the results don't match it. The Thread doesn't relinquish the blocking task(i.e task 1 and task2 ) and moves to non blocking ( task 3 ).
In case of pool size =1 , all tasks execute in sequence whereas I expected Task 3 to complete first as it was non blocking in both cases ( pool size=1 or 2)
What is the actual behaviour of Threads in ForkJoinPool in case of blocking IO ?
ForkJoinPool pool = new ForkJoinPool(1);
List<Future<String>> tasks = new ArrayList<Future<String>>();
//Blocking
tasks.add(pool.submit(() -> { Thread.sleep(10000); System.out.println("Task 1 woke up"+ Thread.currentThread().isDaemon()); return "task1"; }));
//Blocking
tasks.add(pool.submit(() -> { Thread.sleep(10000); System.out.println("Task 2 woke up"+Thread.currentThread().isDaemon()); return "task2"; }));
//Non Blocking
tasks.add(pool.submit(() -> { System.out.println("Task 3 Runs"+Thread.currentThread().isDaemon()); return "task3"; }));
int i=0;
System.out.println("pool size = " + pool.getParallelism() + "Thread count=" +pool.getPoolSize() + "Stealing =" + pool.getStealCount());
System.out.println("waiting");
String str1 = tasks.get(0).get();
String str2 = tasks.get(1).get();
String str3 = tasks.get(2).get();
System.out.println("Results = " + str1+ str2 +str3);
System.out.println("done");
Results :
//Pool size = 2
Task 2 woke uptrue
Task 1 woke uptrue
Task 3 Runstrue
//Pool size = 1
Task 1 woke uptrue
Task 2 woke uptrue
Task 3 Runstrue
Another observation:
When we submit Task 3( non blocking ) first then only it is invoked first.
ForkJoinPool is used only as a scheduler as mentioned in the Loom Proposal. Only Virtual Threads have the ability to relinquish the blocking task and switch to another task. Based on what I remember from reading a mail in the loom mailing list, the loom team is currently not planning to redesign java.util.concurrent's ForkJoinPool to use Virtual Threads.