Java 8流 – stackoverflow异常

前端之家收集整理的这篇文章主要介绍了Java 8流 – stackoverflow异常前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
运行以下代码示例以:
“线程中的异常”主要“ java.lang.StackOverflowError”
  1. import java.util.stream.IntStream;
  2. import java.util.stream.Stream;
  3.  
  4. public class TestStream {
  5.  
  6. public static void main(String[] args) {
  7. Stream<String> reducedStream = IntStream.range(0,15000)
  8. .mapToObj(Abc::new)
  9. .reduce(
  10. Stream.of("Test"),(str,abc) -> abc.process(str),(a,b) -> {throw new IllegalStateException();}
  11. );
  12. System.out.println(reducedStream.findFirst().get());
  13. }
  14.  
  15. private static class Abc {
  16. public Abc(int id) {
  17. }
  18.  
  19. public Stream<String> process(Stream<String> batch) {
  20. return batch.map(this::doNothing);
  21. }
  22.  
  23. private String doNothing(String test) {
  24. return test;
  25. }
  26. }
  27. }

究竟是什么导致了这个问题?这段代码的哪一部分是递归的,为什么?

解决方法

你的代码没有递归循环.您可以使用较小的数字测试IntStream范围(即1或100).在你的情况下,这是导致问题的实际堆栈大小限制.正如在一些评论中指出的,它的流程是进程.

流上的每个调用都会在原始文件周围创建一个新的包装流. ‘findFirst()’方法向前一个流请求元素,这些元素又要求先前的流元素.由于流不是真正的容器,而只是对结果元素的指针.

包装爆炸发生在reduce方法的“累加器”(str,abc) – > abc.process(STR)”.该方法的实现在先前操作的结果(str)上创建一个新的流包装器,进入下一个迭代,在结果(result(str))上创建一个新的包装器).所以累积机制是一个包装(递归)而不是一个appender(迭代)之一.因此,创建一个实际(扁平化)结果的新流,而不是参考潜在的结果将会阻止爆炸,即

  1. public Stream<String> process(Stream<String> batch) {
  2. return Stream.of(batch.map(this::doNothing).collect(Collectors.joining()));
  3. }

这个方法只是一个例子,因为你的原始例子没有任何意义,因为它什么都不做,而且这个例子也不是.它只是一个例证.它基本上将由map方法返回的流的元素平坦化为单个字符串,并在此具体字符串上创建新流,而不是在流本身上,这与您的原始代码的区别.

您可以使用定义每个线程堆栈大小的“-Xss”参数调整堆栈大小.默认值取决于平台,另请参阅此问题‘What is the maximum depth of the java call stack?’但是,在增加时请小心,此设置适用于所有线程.

猜你在找的Java相关文章