我遇到了一个名为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);
}
答案 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个线程,等等。