繁体   English   中英

java 8并行流需要更多时间

[英]java 8 parallel stream takes more time

我正在尝试了解java 8并行流。 我写了下面的代码,首先使用Executor,然后使用并行流。 看起来平行流需要两倍(10秒)的时间与Executor接近(5秒)。 在我看来,并行流也应该表现出类似的性能。 任何想法为什么并行流需要两倍的时间? 我的电脑有8个核心。

/**
 * 
 */
package com.shashank.java8.parallel_stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author pooja
 *
 */
public class Sample {

    public static int processUrl(String url) {

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Running Thread " + Thread.currentThread());
        return url.length();
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        usingExecutor();
        usingParallelStream();
    }

    public static void usingParallelStream() {

        Date start = new Date();
        // TODO Auto-generated method stub
        int total = buildUrlsList().parallelStream().mapToInt(Sample::processUrl).reduce(0, Integer::sum);
        Date end = new Date();
        System.out.println(total);
        System.out.println((end.getTime() - start.getTime()) / 1000);

    }

    public static void usingExecutor() throws Exception {
        Date start = new Date();
        ExecutorService executorService = Executors.newFixedThreadPool(100);
        List<Future> futures = new ArrayList<>();

        for (String url : buildUrlsList()) {
            futures.add(executorService.submit(() -> processUrl(url)));

        }

        // iterate through the future
        int total = 0;
        for (Future<Integer> future : futures) {
            total += future.get();
        }
        System.out.println(total);
        Date end = new Date();
        System.out.println((end.getTime() - start.getTime()) / 1000);

    }

    public static List<String> buildUrlsList() {
        return Arrays.asList("url1", "url2", "url3", "url4", "url5", "url6", "url7", "url8", "url9");

    }

}

解释很简单。 你有8个核心,所以parallelStream()通常可以在8个线程中并行化工作。 他们都立即抓住任务,他们都睡了5秒钟。 然后其中一个接受下一个(第9个)任务,它再睡5秒钟。 然后完成处理。 这意味着约5秒(8个线程)+ 5秒(1个线程)=总共10秒。 但让我们看看这一点。 我稍微修改你的代码:

 public static int processUrl(String url) {

    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println("T[" + Thread.currentThread().getId() + "] finished @[" + System.currentTimeMillis() / 1000 + "]");
    return url.length();
}

使用并行流,您可以获得类似于以下内容的输出:

T[1] finished @[1494267500]
T[12] finished @[1494267500]
T[17] finished @[1494267500]
T[13] finished @[1494267500]
T[14] finished @[1494267500]
T[16] finished @[1494267500]
T[11] finished @[1494267500]
T[15] finished @[1494267500]
T[12] finished @[1494267505]
36
10

请注意,相同的线程T [12]完成任务两次,并在8个任务的第一轮'后完成5秒。

使用线程执行程序,您创建了100个线程。 因此,9个线程每个抓取一个任务,执行时间约为5秒,因为线程池不会耗尽:

T[14] finished @[1494267783]
T[11] finished @[1494267783]
T[19] finished @[1494267783]
T[17] finished @[1494267783]
T[12] finished @[1494267783]
T[16] finished @[1494267783]
T[13] finished @[1494267783]
T[15] finished @[1494267783]
T[18] finished @[1494267783]
36
5

请注意,此处没有具有相同ID的线程。 (这不是为固定池选择通用线程数的建议:-)我只是详细说明你的实际问题)。

试用调度程序并分配8个线程:

ExecutorService executorService = Executors.newFixedThreadPool(8);

然后执行时间可能大致相同,因为线程池将耗尽。 如果URL-s只有8而不是9,您会注意到类似的性能。

当然,无法保证此代码在不同环境中的行为相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM