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
相关产品推荐
相关产品推荐

