简体   繁体   中英

RecursiveTask thread is not blocked by join()

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM