1、不小心创建了一个”无限"流
你可能一不留神就创建了一个无限流。就拿下面这个例子来说:
Java代码
1. IntStream.iterate(0, i -> i + 1)
2. .forEach(System.out::println);
流的问题就在于它有可能是无限的,如果你的确是这样设计的话。唯一的问题就是,这并不是你真正想要的。因此,你得确保每次都给流提供一个适当的大小限制:
Java代码
1. // That's better
2. IntStream.iterate(0, i -> i + 1)
3. .limit(10)
4. .forEach(System.out::println);
2、 不小心创建了一个“隐藏的”无限流
这个话题是说不完的。你可能一不小心就真的创建了一个无限流。比如说下面的这个:
Java代码
1. IntStream.iterate(0, i -> ( i + 1 ) % 2)
2. .distinct()
3. .limit(10)
4. .forEach(System.out::println);
这样做的结果是:
· 我们生成了0和1的交替数列
· 然后只保留不同的数值,比如说,一个0和一个1
· 然后再将流的大小限制为10
· 最后对流进行消费
好吧,这个distinct()操作它并不知道iterate()所调用的这个函数生成的只有两个不同的值。它觉得可能还会有别的值。因此它会不停地从流中消费新的值,而这个limit(10)永远也不会被调用到。不幸的是,你的应用程序会崩掉。
3、 不小心创建了一个”隐藏”的并行无限流
我还是想继续提醒下你,你可能真的一不小心就消费了一个无限流。假设你认为distinct()操作是会并行执行的。那你可能会这么写:
1. IntStream.iterate(0, i -> ( i + 1 ) % 2)
2. .parallel()
3. .distinct()
4. .limit(10)
5. .forEach(System.out::println);
现在我们可以知道的是,这段代码会一直执行下去。不过在前面那个例子中,你至少只消耗了机器上的一个CPU。而现在你可能会消耗四个,一个无限流的消费很可能就会消耗掉你整个系统的资源。这可相当不妙。这种情况下你可能得去重启服务器了。
4、.并行流死锁
如果你没有正确地进行同步的话,所有的并发系统都可能碰到死锁。现实中的例子可能不那么明显,不过如果你想自己创造一个场景的话倒是很容易。下面这个parallel()流肯定会造成死锁:Java代码
1. Object[] locks = { new Object(), new Object() };
2.
3. IntStream
4. .range(1, 5)
5. .parallel()
6. .peek(Unchecked.intConsumer(i -> {
7. synchronized (locks[i % locks.length]) {
8. Thread.sleep(100);
9.
10. synchronized (locks[(i + 1) % locks.length]) {
11. Thread.sleep(50);
12. }
13. }
14. }))
15. .forEach(System.out::println);
注意这里Unchecked.intConsumer()的使用,它把IntConsumer接口转化成了 org.jooq.lambda.fi.util.function.CheckedIntConsumer,这样你才可以抛出已检查异常。