10. Stream流 --- 串行流/并行流/普通for循环对比

93 阅读2分钟

10. Stream流 --- 串行流/并行流/普通for循环对比

1. 串行Stream流

之前的一篇文章都是串行的Stream流,也就是再一个线程上面执行。

串行流的效率低。

@Test
@DisplayName("串行流单线程的验证")
public void test24() {
    long count = Stream.of(5, 6, 8, 3, 4, 0).filter(s -> {
        System.out.println(Thread.currentThread() + " " + s);
        return s > 3;
    }).count();
    System.out.println(count);
}

Result:

Thread[main,5,main] 5
Thread[main,5,main] 6
Thread[main,5,main] 8
Thread[main,5,main] 3
Thread[main,5,main] 4
Thread[main,5,main] 0
4

2. 并行流

paralleStream其实就是一个并行执行的流,它通过默认的ForkJoinPool,可以提高多线程任务的速度。

获取并行流的两种方式

  • 1.通过List接口中的parallelStream方法来获取
    1. 通过已有的串行流转换为并行流

方式a:通过List接口中的parallelStream方法来获取

@Test
@DisplayName("通过List接口中的parallelStream方法来获取")
public void test25() {

    ArrayList<Integer> list = new ArrayList<>();

    // 通过List接口直接获取并行流
    Stream<Integer> integerStream = list.parallelStream();

}

方式b:通过已有的串行流转换为并行流

@Test
@DisplayName("通过已有的串行流转换为并行流")
public void test26() {

    // 通过已有的串行流转换为并行流
    Stream<Integer> parallel = Stream.of(1, 2, 3).parallel();
    
}

并行(并发)流操作

将流转换为并发流,Stream处理的时候就会通过多线程处理

@Test
@DisplayName("【案例】:并行流操作")
public void test27() {

    long count = Stream.of(1, 4, 6, 7, 3)
            .parallel()
            .filter(s -> {
                System.out.println(Thread.currentThread() + "s = " + s);
                return s > 2;
            }).count();
    System.out.println("count = " + count);
}
Thread[ForkJoinPool.commonPool-worker-4,5,main]s = 7
Thread[ForkJoinPool.commonPool-worker-3,5,main]s = 1
Thread[ForkJoinPool.commonPool-worker-2,5,main]s = 3
Thread[ForkJoinPool.commonPool-worker-1,5,main]s = 4
Thread[main,5,main]s = 6
count = 4

并行流和串行流对比

通过for循环,串行Stream流,并行流来对1000000000个数字求和,来看消耗时间。

1. 普通for循环

// 10亿
private static long times = 1000000000;

private long start;

@Before
public void before(){
    start = System.currentTimeMillis();
}
@org.junit.Test
@DisplayName("普通for循环")
public void test28() {

    long res = 0;

    for (int i = 0; i < times ; i++) {
        res +=i;
    }
    System.out.println("res = " + res);
}
@After
public void end() {
    long end = System.currentTimeMillis();
    System.out.println("消耗时间" + (end - start));
}
res = 499999999500000000
消耗时间467

2. 串行流

@org.junit.Test
@DisplayName("串行流")
public void test29() {
    long reduce = LongStream.rangeClosed(0, times).reduce(0, Long::sum);
    System.out.println(reduce);
}
500000000500000000
消耗时间607

3. 并行流

@org.junit.Test
@DisplayName("并行流")
public void test30() {
    long reduce = LongStream.rangeClosed(0, times).parallel().reduce(0, Long::sum);
    System.out.println(reduce);
}
500000000500000000
消耗时间225

通过上面的普通for循环串行流并行流 可以发现,再10亿条数据进行累加求和的时候,并行效率最高。 但是要合理选择,数据量小的时候,并行流的速度并不一定快。

Stream并行流处理的过程会分而治之,也就是将一个大的任务切分成了多个小任务,这表示每个任务都是一个线程操作。