我有以下代码:
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();
}
}我希望代码不会在叉()状态中打开新线程,
因为的并行性是1。
但是,该代码的输出是:
线程启动,threadId=11 n=5 activeCount=3
线程启动,threadId=11 n=3 activeCount=3
线程启动,threadId=11 n=1 activeCount=3
线程启动,threadId=11 n=2 activeCount=3线程启动,threadId=11 n=0 activeCount=3
线程启动,threadId=11 n=1 activeCount=3
线程完成,threadId=11 n=2 activeCount=3 result=1
线程完成,threadId=11 n=3 activeCount=3 result=2
线程启动,threadId=11 n=4 activeCount=3
线程启动,threadId=11 n=2 activeCount=3
线程启动,threadId=11 n=0 activeCount=3线程启动,threadId=11 n=1 activeCount=3
线程完成,threadId=11 n=2 activeCount=3 result=1
线程启动,threadId=11 n=3 activeCount=3
线程启动,threadId=11 n=1 activeCount=3
线程启动,threadId=11 n=2 activeCount=3
线程启动,threadId=11 n=0 activeCount=3线程启动,threadId=11 n=1 activeCount=3
线程完成,threadId=11 n=2 activeCount=3 result=1
线程完成,threadId=11 n=3 activeCount=3 result=2
线程完成,threadId=11 n=4 activeCount=3 result=3
线程完成,threadId=11 n=5 activeCount=3 result=5
从输出打印来看,我们一次有12个线程处于活动状态。
新线程是如何打开的,尽管的并行性是1?
发布于 2019-11-30 19:07:38
连接()在Fork池中与经典的线程连接不同。
join ()在Java线程中用作屏障同步器,以等待另一个线程完成,然后与其连接(在完成另一个线程之前不能继续)。常规线程中的联接会阻塞调用线程。
join()在Fork池中并不是简单地阻塞调用线程,而是使用工作线程来帮助运行子任务。
当workerThread遇到join()时,它会处理任何其他任务,直到它注意到目标子任务已经完成为止。
在这个子任务结果完成之前,workerThread不会返回给调用方。
一个 join() 在Fork-Join 任务中不是阻塞的,它包含当前的任务,因此只有在join()创建的子任务完成之后,计算才会继续。
工作线程指出,任务被阻塞,直到子任务完成,所以它开始工作在子任务上。
ForkJoinTask比Java线程轻。一个真正的Java线程有它自己的堆栈、寄存器,以及许多其他的资源,这些资源允许由线程调度程序独立地管理它,这些资源是操作系统内部拥有的。
在ForkJoinTask中,大量的ForkJoinTask可以在少得多的WorkerThreads中运行。每个WorkerThread都是一个Java线程对象,它具有您期望从一个普通线程获得的所有设备。
https://stackoverflow.com/questions/59099949
复制相似问题