简体   繁体   English

如何在Java parallelStream中使用print(“\\ r”+ progressMessage)?

[英]How to use print(“\r”+progressMessage) in a Java parallelStream?

I am trying to display a progress for my parallelStream by writing something like 我试图通过编写类似的东西来显示我的parallelStream的进度

int total=myList.size();
AtomicInteger counter=new AtomicInteger(0);

List<String> myResult=IntStream.range(0, total)
                    .parallel()
                    .mapToObj(i-> modify(myList.get(i)))
                    .peek(i->System.out.print("\r"+(counter.getAndIncrement()*100/total)+"%"))
                    .collect(toList());

My problem comes from the "\\r". 我的问题来自“\\ r”。 Given that it's parallelized, the amount of "\\r" needed to really go to the beginning of the line may vary when concurrent events occur. 鉴于它是并行化的,当并发事件发生时,真正到达行开头所需的“\\ r”的数量可能会有所不同。 So I can read sometimes "70% 71%"... 所以我有时读“70%71%”......

Separate the progress recording from the progress output operation: 将进度记录与进度输出操作分开:

int total = myList.size();
AtomicInteger counter = new AtomicInteger(0);
ScheduledExecutorService es = Executors.newScheduledThreadPool(1);

ScheduledFuture<?> f = es.scheduleWithFixedDelay(new Runnable() {
    int lastReported = -1;
    public void run() {
        int newValue = counter.get();
        if(newValue != lastReported) {
            lastReported = newValue;
            System.out.append("\r"+newValue*100/total+"%").flush();
        }
    }
}, 100, 100, TimeUnit.MILLISECONDS);

List<String> myResult = IntStream.range(0, total)
    .parallel()
    .mapToObj(i -> modify(myList.get(i)))
    .peek(i -> counter.incrementAndGet())
    .collect(toList());

f.cancel(true);
es.shutdown();
System.out.print("\r100%");

Now, the printing is done consistently by one thread. 现在,打印由一个线程一致地完成。 This separation solves even more issues. 这种分离解决了更多问题。 Performing a print operation for every element will slow down your actual processing significantly. 对每个元素执行打印操作会显着降低实际处理速度。 By using a scheduled printing job, you can control the overhead yourself, ie you don't need printing faster than a human can read and you don't need to perform an expensive printing operation if the percentage did not change since the last update. 通过使用预定的打印作业,您可以自己控制开销,即您不需要比人类可以读取更快的打印,并且如果自上次更新后百分比没有变化,则无需执行昂贵的打印操作。

Note that by the time, all elements have passed the peek action, the stream operation has not entirely completed (there's at least one merge operation pending), but that's the best progress estimate you can get with the current API. 请注意,到时候,所有元素都已经通过了peek动作,流操作还没有完全完成(至少有一个合并操作挂起),但这是使用当前API可以获得的最佳进度估计。

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

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