首页 > 解决方案 > 如何检查 Java 8 Stream.forEach() 何时完成迭代?

问题描述

我想使用 Java 8Stream提供的并行性,但我还需要以特定顺序完成某些操作,否则一切都会中断。问题是使用流意味着代码现在是异步的[注意:这是不正确的],我无法弄清楚如何仅在完成对整个集合的迭代时才发生某些事情。[注意:这是自动发生的]

现在,我的代码如下:

    public void iterateOverMap(Map<String, String> m)
    {
        AtomicInteger count = new AtomicInteger(0);
        
        m.keySet().stream().forEach((k) -> {
                    Object o = m.get(k);
                    
                    // do stuff with o
                    
                    count.incrementAndGet();
                });
        
        // spin up a new thread to check if the Stream is done
        new Thread(() -> {
            for (;;)
            {
                if (count.intValue() >= map.size())
                    break;
            }
            afterFinishedIterating();
        }).start();
    }

我不喜欢为了跟踪这件事而不得不启动一个新线程或阻塞主线程的想法,但我想不出我还能怎么做。有谁知道更好的选择?

谢谢!

标签: javaforeachparallel-processingjava-streamthread-synchronization

解决方案


Stream处理是同步的。

如果您想要一个如何跟踪 a 进度的示例Stream,您可以使用peek()中间操作,但请记住,它最好用于调试目的

取自我的其他答案的示例

Stream<MyData> myStream = readData();
final AtomicInteger loader = new AtomicInteger();
int fivePercent = elementsCount / 20;
MyResult result = myStream
    .map(row -> process(row))
    .peek(stat -> {
        if (loader.incrementAndGet() % fivePercent == 0) {
            System.out.println(loader.get() + " elements on " + elementsCount + " treated");
            System.out.println((5*(loader.get() / fivePercent)) + "%");
        }
    })
    .reduce(MyStat::aggregate);

推荐阅读