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

时间:2021-05-17 20:59:23

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". 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. So I can read sometimes "70% 71%"...

我的问题来自“\ r \ n”。鉴于它是并行化的,当并发事件发生时,真正到达行开头所需的“\ r”的数量可能会有所不同。所以我有时读“70%71%”......

1 个解决方案

#1


2  

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, i.e. 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可以获得的最佳进度估算。

#1


2  

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, i.e. 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可以获得的最佳进度估算。