I have the following code:
public class Main {
public static void main(String[] args) {
ExecutorService executorService = Executors.newWorkStealingPool(1);
ForkJoinPool workStealingPool = (ForkJoinPool)executorService;
RecursiveRunnable recursiveRunnable = new RecursiveRunnable(5);
workStealingPool.invoke(recursiveRunnable);
}
}
public class RecursiveRunnable extends RecursiveTask<Integer> implements Runnable {
private final int n;
public RecursiveRunnable(int n) {
this.n = n;
}
@Override
@SneakyThrows
protected Integer compute() {
Thread thread = Thread.currentThread();
System.out.println("Thread started, threadId=" + thread.getId() + " n=" + n + " activeCount=" + Thread.activeCount());
if (n <= 1) {
return n;
}
RecursiveRunnable f1 = new RecursiveRunnable(n - 1);
f1.fork();
RecursiveRunnable f2 = new RecursiveRunnable(n - 2);
f2.fork();
int result = 0;
result = f2.get() + f1.get();
System.out.println("Thread finished, threadId=" + thread.getId() + " n=" + n + " activeCount=" + Thread.activeCount() + " result=" + result);
return result;
}
@Override
public void run() {
compute();
}
}
I expect from the code not to open new threads in the fork() statment,
since the parallelism is 1 .
But the output of this code is:
Thread started, threadId=11 n=5 activeCount=3
Thread started, threadId=11 n=3 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread started, threadId=11 n=2 activeCount=3
Thread started, threadId=11 n=0 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread finished, threadId=11 n=2 activeCount=3 result=1
Thread finished, threadId=11 n=3 activeCount=3 result=2
Thread started, threadId=11 n=4 activeCount=3
Thread started, threadId=11 n=2 activeCount=3
Thread started, threadId=11 n=0 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread finished, threadId=11 n=2 activeCount=3 result=1
Thread started, threadId=11 n=3 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread started, threadId=11 n=2 activeCount=3
Thread started, threadId=11 n=0 activeCount=3
Thread started, threadId=11 n=1 activeCount=3
Thread finished, threadId=11 n=2 activeCount=3 result=1
Thread finished, threadId=11 n=3 activeCount=3 result=2
Thread finished, threadId=11 n=4 activeCount=3 result=3
Thread finished, threadId=11 n=5 activeCount=3 result=5
From the output print it looks like we have 12 threads alive at one time.
How new threads are open although the parallelism is 1 ?
join() in a Fork-Join pool is different from the classic Java thread join.
join() in Java thread is used as a barrier syncronizer to wait for another thread to finish and then you join with it (You can't proceed until the other one is done). A join in a regular thread blocks the calling thread.
The join() in a Fork-Join pool doesn't simply block the calling thread, instead, the worker thread is used to to help run the sub-tasks.
When the workerThread encounteres a join() it processes any other tasks until it notices the target sub-task is done.
The workerThread doesn't return to the caller until this sub-tasks results are finished.
A join() in a Fork-Join pool task is not block, it holds the current task, so the computation to be continued only after it's sub-tasks created by the join() finished.
The worker thread figures out, that the task is blocked till the sub- task is finished so it start to work on the sub-task.
A ForkJoinTask is lighter than a Java thread. A real Java thread has it's own stack, registers, a lot of other resources that allow it to be scheduled independently managed by the thread scheduler, that the operating system has internally.
A larg number of ForkJoinTask can run in a much smaller number of WorkerThreads in the Fork-Join-Pool. Each WorkerThread is a Java thread object with all it's accoutrements that you expect from a normal thread.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.