java - 并行流处理 vs 线程池处理 vs 顺序处理

标签 java multithreading java-8 java-stream

我只是在评估,哪些代码片段在 Java 8 中表现更好。

Snippet 1(在主线程中处理):

public long doSequence() {
    DoubleStream ds = IntStream.range(0, 100000).asDoubleStream();
    long startTime = System.currentTimeMillis();
    final AtomicLong al = new AtomicLong();
    ds.forEach((num) -> {
        long n1 = new Double (Math.pow(num, 3)).longValue();
        long n2 = new Double (Math.pow(num, 2)).longValue();
        al.addAndGet(n1 + n2);
    });
    System.out.println("Sequence");
    System.out.println(al.get());
    long endTime = System.currentTimeMillis();
    return (endTime - startTime);
}

片段 2(在并行线程中处理):

public long doParallel() {
    long startTime = System.currentTimeMillis();
    final AtomicLong al = new AtomicLong();
    DoubleStream ds = IntStream.range(0, 100000).asDoubleStream();
    ds.parallel().forEach((num) -> {
        long n1 = new Double (Math.pow(num, 3)).longValue();
        long n2 = new Double (Math.pow(num, 2)).longValue();
        al.addAndGet(n1 + n2);
    });
    System.out.println("Parallel");
    System.out.println(al.get());
    long endTime = System.currentTimeMillis();
    return (endTime - startTime);
}

片段 3(在线程池的并行线程中处理):

public long doThreadPoolParallel() throws InterruptedException, ExecutionException {
    ForkJoinPool customThreadPool = new ForkJoinPool(4);
    DoubleStream ds = IntStream.range(0, 100000).asDoubleStream();
    long startTime = System.currentTimeMillis();
    final AtomicLong al = new AtomicLong();
    customThreadPool.submit(() -> ds.parallel().forEach((num) -> {
        long n1 = new Double (Math.pow(num, 3)).longValue();
        long n2 = new Double (Math.pow(num, 2)).longValue();
        al.addAndGet(n1 + n2);
    })).get();
    System.out.println("Thread Pool");
    System.out.println(al.get());
    long endTime = System.currentTimeMillis();
    return (endTime - startTime);
}

输出在这里:

Parallel
6553089257123798384
34 <--34 milli seconds

Thread Pool
6553089257123798384
23 <--23 milli seconds

Sequence
6553089257123798384
12 <--12 milli seconds!

我期望的是

1) 使用线程池处理的时间应该是最短的,但事实并非如此。(注意我没有包括线程池创建时间,所以它应该很快)

2) 没想到顺序运行的代码是最快的,应该是什么原因。

我使用的是四核处理器。

感谢任何帮助解释上述歧义的人!

最佳答案

您的比较并不完美,肯定是因为缺少 VM 预热。当我简单地重复执行时,我得到不同的结果:

System.out.println(doParallel());
System.out.println(doThreadPoolParallel());
System.out.println(doSequence());
System.out.println("-------");
System.out.println(doParallel());
System.out.println(doThreadPoolParallel());
System.out.println(doSequence());
System.out.println("-------");
System.out.println(doParallel());
System.out.println(doThreadPoolParallel());
System.out.println(doSequence());

结果:

Parallel
6553089257123798384
65
Thread Pool
6553089257123798384
13
Sequence
6553089257123798384
14
-------
Parallel
6553089257123798384
9
Thread Pool
6553089257123798384
4
Sequence
6553089257123798384
8
-------
Parallel
6553089257123798384
8
Thread Pool
6553089257123798384
3
Sequence
6553089257123798384
8

正如@Erwin 在评论中所指出的,请查看 this question 上的答案(在本例中为规则 1)有关如何正确执行此基准测试的想法。

并行流的默认并行性不一定与 fork 连接池提供的并行性相同,线程数与计算机上的内核一样多,尽管当我从你的切换时结果之间的差异仍然可以忽略不计自定义池到通用分支加入池。

关于java - 并行流处理 vs 线程池处理 vs 顺序处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50167559/

相关文章:

java - 在 while 循环中验证 isDisplayed() WebElement 属性

java - 来自 jtree 中 jcheckbox 的多个 ITEM_STATE_CHANGED 事件

java - 如何使用 Mockito 测试和模拟用 Java 编写的 GRPC 服务

Java:这个单例类变量赋值线程安全吗?

java - 当线程尝试调用静态和非静态同步方法时会发生什么?

java - 连接列表中所有 map 的字符串值

java-8 - Java 8 - 如何在 java 8 中进行过滤以从不同类别的菜肴类型中获取结果?

java - 幂函数指数 JOptionPane java

c - 多线程程序在 HTTPS 请求上崩溃

java - .collect(Collectors.toList()) 和 Java 方法上的流