You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中基本类型变量未执行赋值却自动变更的问题排查

单独线程运行的进度条仅打印一次后不再更新

我编写了一个终端进度条类,让它在单独线程中运行,避免影响调用线程的性能。为防止进度条循环打印导致终端闪烁,我添加了lastProgress变量,仅在打印进度条后更新它,预期只有当progress(进度跟踪变量)通过step()方法增加时才重新打印进度条。

但实际运行时,进度条仅打印一次就不再更新。跟踪progress和lastProgress的值发现,每次progress增加时lastProgress也随之增加,但代码中唯一更新lastProgress的代码从未执行。我甚至用javap反编译查看字节码,确认不是Java基本类型按值传递的问题。

以下是我的代码:

package utils;

public class ProgressBar implements Runnable {
  private String message;
  private final float maxProgress;
  private float progress;
  private float lastProgress;
  private boolean running;
  private final int PROGRESS_BAR_LENGTH = 50;

  public ProgressBar(String message, int maxProgress) {
    this.maxProgress = maxProgress;
    this.message = message;
    progress = 0;
    lastProgress = 0;
    running = true;
  }

  @Override
  public void run() {
    StringBuilder s;

    while (running) {
      // 打印判断逻辑
      if (progress > lastProgress) {
        s = new StringBuilder();
        float progressLevel = (progress / maxProgress) * PROGRESS_BAR_LENGTH;
        s.append("┃");
        for (int i = 1; i <= PROGRESS_BAR_LENGTH; i++) {
          if (i <= progressLevel) s.append("█");
          else s.append(" ");
        }
        s.append("┃");

        System.out.printf(
            "%s:    %s    %.0f%% \r", message, s, progressLevel * (100 / PROGRESS_BAR_LENGTH));

        // 这是唯一更新lastProgress的地方
        lastProgress = progress;
      }
    }

    // 确保显示最终更新的打印逻辑
    s = new StringBuilder();
    float progressLevel = (progress / maxProgress) * PROGRESS_BAR_LENGTH;
    s.append("┃");
    for (int i = 1; i <= PROGRESS_BAR_LENGTH; i++) {
      if (i <= progressLevel) s.append("█");
      else s.append(" ");
    }
    s.append("┃");

    System.out.printf(
        "%s:    %s    %.0f%% \r", message, s, progressLevel * (100 / PROGRESS_BAR_LENGTH));
  }

  public void step() {
    progress++;
    if (progress >= maxProgress) {
      progress = maxProgress;
      running = false;
    }
  }

  public void step(float step) {
    progress += step;
    if (progress >= maxProgress) {
      progress = maxProgress;
      running = false;
    }
  }

  public void setMessage(String newMessage) {
    message = newMessage;
  }

  public void stepTo(int newProgress) {
    progress = newProgress;
    if (progress > maxProgress) {
      progress = maxProgress;
      running = false;
    }
  }

  public static void main(String[] args) throws InterruptedException {
    ProgressBar pb = new ProgressBar("Test", 100);
    new Thread(pb).start();

    for (int i = 0; i < 100; i++) {
      pb.step();
      Thread.sleep(2000);
    }
  }
}

补充说明:我之前误用了“多线程”一词,实际是让进度条程序在单独线程运行以避免影响调用线程性能;且无需考虑线程安全,只会运行一个实例并自行管理内部状态。

内容的提问来源于stack exchange,提问作者Christo Swanepoel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 01:47:11