Java双线程逆序打印字符串每字符两次 如何保证输出稳定正确
问题根源
你当前的代码存在两个核心问题,导致输出结果随机、不符合预期:
- 循环变量
i是每个线程运行run方法时的局部变量,两个线程会各自独立完成一遍完整的字符串逆序遍历打印,本质是各打一遍完整逆序串,根本无法实现「每个字符连续打印两次」的要求 - 打印操作没有做任何并发同步控制,JVM调度线程的顺序是随机的,两个线程的打印指令会互相穿插,输出顺序自然无法固定。
修正后代码
public class Print implements Runnable { private String string; // 共享的当前打印索引,初始指向字符串最后一位 private int currentIndex; // 共享的当前字符打印计数 private int printCount; Print(String string) { this.string = string; this.currentIndex = string.length() - 1; this.printCount = 0; } @Override public void run() { while (currentIndex >= 0) { // 加锁保证同一时间只有一个线程执行打印逻辑 synchronized (this) { // 二次校验索引合法性,避免并发下索引越界 if (currentIndex < 0) { break; } // 打印当前字符+连字符 System.out.print(string.charAt(currentIndex) + "-"); printCount++; // 当前字符打印满2次,移动到前一个字符,重置计数 if (printCount == 2) { currentIndex--; printCount = 0; } } } } } public class Task1 { public static void main(String[] args) { Print r = new Print("NAME"); Thread t1 = new Thread(r); Thread t2 = new Thread(r); t1.start(); t2.start(); } }
实现逻辑说明
- 将打印位置索引、单字符打印计数设为Runnable实例的共享变量,两个线程操作同一份状态数据,不会再出现各自遍历全串的问题
- 用
synchronized给打印逻辑块加实例锁,保证打印操作的原子性,彻底避免两个线程的输出内容穿插错乱 - 锁内增加索引合法性二次判断,规避极端调度场景下的字符串索引越界异常
- 严格控制索引移动时机:仅当当前字符完成两次打印后,才将索引前移一位并重置打印计数,保证输出顺序固定为逆序、每个字符连续打印两次,运行后始终输出
E-E-M-M-A-A-N-N-符合要求。
内容的提问来源于stack exchange,提问作者Robert Kocev
相关产品推荐
相关产品推荐

