有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程如何知道Fork和Join在Java中是否有足够的池大小?

我正在尝试对一些大数据实施分而治之的解决方案。我使用fork和join将事物分解成线程。但是,我有一个关于fork机制的问题:如果我将分治条件设置为:

@Override
protected SomeClass compute(){
    if (list.size()<LIMIT){
        //Do something here
        ...
    }else{
        //Divide the list and invoke sub-threads
        SomeRecursiveTaskClass subWorker1 = new SomeRecursiveTaskClass(list.subList());
        SomeRecursiveTaskClass subWorker2 = new SomeRecursiveTaskClass(list.subList());
        invokeAll(subWorker1, subWorker2);
        ...
    }
}

如果没有足够的资源来调用subWorker(例如池中没有足够的线程),会发生什么情况?Fork/Join框架是否为可用线程维护池大小?或者我应该在分而治之的逻辑中加入这个条件


共 (1) 个答案

  1. # 1 楼答案

    每个ForkJoinPool都有一个配置的目标parallelism。这与线程的数量并不完全匹配,也就是说,如果工作线程将通过^{}等待,那么池可能会启动更多线程来进行补偿。^{}的并行性默认为“CPU核数减一”,因此当将启动的非池线程合并为辅助线程时,生成的并行性将利用所有CPU核

    当提交的作业多于线程时,它们将排队。将几个作业排队有助于利用线程,因为并非所有作业都可以完全同时运行,因此工作不足的线程可能会从其他线程窃取作业,但拆分工作过多可能会产生不必要的开销

    因此,您可以使用^{}获取当前挂起的作业数,这些作业不太可能被其他线程窃取,并且只有在低于一个小阈值时才会被分割。正如其文件所述:

    This value may be useful for heuristic decisions about whether to fork other tasks. In many usages of ForkJoinTasks, at steady state, each worker should aim to maintain a small constant surplus (for example, 3) of tasks, and to process computations locally if this threshold is exceeded.

    因此,这是决定是否进一步拆分工作的条件。因为这个数字反映了空闲线程窃取创建的作业的时间,所以当作业具有不同的CPU负载时,它将导致平衡。此外,它的工作原理是相反的,如果池是共享的(就像公共池一样),线程已经很忙,它们将不会接收您的作业,剩余计数将保持较高,然后您将自动停止拆分