Fork加入池理解

时间:2018-01-03 08:36:17

标签: java multithreading

我遇到了一个名为ForkJoinPool的java.util.concurrent包中的新类 据我了解,它使用以下方案:

将大任务划分为子任务(fork),当每个任务完成时,收集所有子任务(join),然后合并它。

Fork join pool有一个构造函数public ForkJoinPool(int parallelism) 从官方文档中我已经阅读了以下内容:

  

通过将自身分成子任务,可以执行每个子任务   由不同的CPU并行,或同一CPU上的不同线程。

问题是如何设置forkjoinpool的线程数量。

contructor中的parallelism是指线程数量还是处理器数量。如果是处理器数量,请考虑以下代码:

Runtime.getRuntime().availableProcessors()
return 4

这是否意味着以下ForkJoinPool pool = new ForkJoinPool(8);无效,因为我的电脑只有4个处理器?

代码示例

public static void main(String[] args) throws Exception {

        ForkJoinPool pool = new ForkJoinPool(8);
        final List<String> list = Arrays.asList("dasd","dasd")//for example 300 hundrends strings;
        pool.submit(()->{
            list.parallelStream().forEach(AvailableProc::test);
        }).get();

    }

    public static void test(final String code){
            Thread.sleep(1000);     
            System.out.println(code);
    }

4 个答案:

答案 0 :(得分:2)

  

contructor中的parallelism是指线程数量还是处理器数量

parallelism参数告诉ForkJoinPool要使用多少个工作线程。默认情况下,它等于可用的处理器数量,这通常是最佳的。当然,你可以在这里设置任何数字,但设置它大于最有可能不会受益的处理器数量。

  

这是否意味着以下ForkJoinPool pool = new ForkJoinPool(8);无效,因为我的电脑只有4个处理器?

这取决于你的实际任务。例如,您的代码示例将每秒打印 8 个字符串:您有8个线程,操作系统将使用context switching在4个处理器上安排所有这些字符串。由于大多数时候线程只是在等待,并且执行时间非常短,因此每秒可以获得8个字符串。

答案 1 :(得分:1)

如果过度分配工作线程数,则只需要从CPU核心绑定和取消绑定的线程。这可能会影响性能,也可能不会影响性能,具体取决于您的工作流程(以及线程正在处理的任务被I / O阻止的频率)。

请注意,默认值是CPU核心数,但没有迹象表明它是上限。

答案 2 :(得分:0)

&#34;此实现将最大运行线程数限制为32767.尝试创建大于最大数量的池会导致IllegalArgumentException。&#34;来自ForkJoinPool - Java8 API doc

答案 3 :(得分:0)

在大多数英特尔处理器中都有一个称为hyper-threading的概念。简单来说,这意味着-如果您拥有四核(4 CPU)计算机,它将允许您运行8个线程。其中四个是真实线程,四个是虚拟线程。在双核中,您可以运行4个线程(2个真实线程和2个虚拟线程)

如果我运行与在Mac笔记本上写的相同程序(Quad-Core Intel Core i7),则由于8线程并行运行,我将获得最优化的时间,因为我的处理器启用了超线程

如果您的计算机CPU未启用超线程,则您将能够在双核计算机中并行运行2个线程,在四核中运行4个线程,在八核中运行8个线程,等等。