Skip to content
java


package com.fm.boot.util;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.*;
import java.time.Duration;
import java.time.Instant;

@Slf4j
public class ProgressTracker {
    private final AtomicInteger completedTasks = new AtomicInteger(0);
    private final int totalTasks;
    private final String taskName;
    private ScheduledExecutorService scheduler;
    private Instant startTime;
    private final ExecutorService executor;

    public ProgressTracker(int totalTasks, String taskName, ExecutorService executor) {
        this.totalTasks = totalTasks;
        this.taskName = taskName;
        this.executor = executor;
    }

    // 启动进度监控
    public void start() {
        startTime = Instant.now();
        scheduler = Executors.newSingleThreadScheduledExecutor();

        // 每秒输出一次进度
        scheduler.scheduleAtFixedRate(this::logProgress, 0, 5, TimeUnit.SECONDS);
    }

    // 停止进度监控
    public void stop() {
        if (scheduler != null && !scheduler.isShutdown()) {
            scheduler.shutdown();
            executor.shutdown();
        }
    }

    // 增加已完成的任务
    public void increment() {
        completedTasks.incrementAndGet();
    }

    private void logProgress() {

        if (completedTasks.get() >= totalTasks) {
            stop();
            return;
        }

        int current = completedTasks.get();

        // 避免除以零
        if (current == 0) {
            return;
        }

        double progress = (double) current / totalTasks * 100;

        // 计算已花费时间和剩余时间
        long elapsedTime = Duration.between(startTime, Instant.now()).toMillis();
        long estimatedTime = (elapsedTime * totalTasks) / current;
        long remainingTime = estimatedTime - elapsedTime;


        // 格式化时间为易读格式
        String elapsedTimeStr = formatTime(elapsedTime);
        String estimatedTimeStr = formatTime(estimatedTime);
        String remainingTimeStr = formatTime(remainingTime);

        // 个/s
        long ps = current / (elapsedTime / 1000);

        // s/个
        long sp = ((elapsedTime / 1000) / current);

        log.info("[{}] 当前进度: {}/{} ({}%) 已花费时间: {} 预计总时间: {} 剩余时间: {} - {}个/s - {}s/个",
                taskName, current, totalTasks, (int) progress,
                elapsedTimeStr, estimatedTimeStr, remainingTimeStr, ps, sp);
    }

    // 格式化时间为小时、分钟、秒
    private String formatTime(long millis) {
        if (millis >= 3600000) {
            long hours = millis / 3600000;
            long minutes = (millis % 3600000) / 60000;
            return String.format("%dh %dm", hours, minutes);
        } else if (millis >= 60000) {
            long minutes = millis / 60000;
            long seconds = (millis % 60000) / 1000;
            return String.format("%dm %ds", minutes, seconds);
        } else {
            long seconds = millis / 1000;
            return String.format("%ds", seconds);
        }
    }
}

✨ 网站运行时间: 3年11月15天 ❤️ 道阻且长,行则将至 - 微信号: heikedreamer