Java:解决按'c'退出随机数生成循环的逻辑问题及do-while改while实现
核心问题定位
- 输入读取逻辑放错位置:原代码把
scanner.next()写在循环外,程序一启动就阻塞等用户输入,根本不会先启动循环 - 循环条件逻辑反转:原代码
while (c == 'c')意思是只有输入c才会继续循环,和实际需求完全相反,应该是未输入c就一直循环,输入c就退出 - 单线程读写冲突:直接在主循环里读输入会阻塞循环,没法同时执行随机数生成和输入监听,必须拆成两个线程
- 语法错误:Java循环判断必须是布尔类型,没有C语言那种
while(1)的写法,你之前写while(1)会直接编译不通过,自然没法生效 - 冗余判断:原代码相邻数对比的else分支永远不会触发,所有整数大小关系都被前面三个判断覆盖了,不需要保留
修正后的do-while版本
核心改动:用volatile修饰运行标志位(保证多线程可见性),单独开线程监听用户输入,主循环直接启动不需要等输入:
import java.util.Random; import java.util.Scanner; public class Main { // volatile修饰保证子线程修改的状态能被主线程立即感知 private static volatile boolean isRunning = true; public static void main(String[] args) { Random rand = new Random(); int[] randNumber = new int[100]; // 输入监听线程,不阻塞主循环 new Thread(() -> { Scanner scanner = new Scanner(System.in); while (isRunning) { if (scanner.hasNext()) { char input = scanner.next().charAt(0); if (input == 'c') { isRunning = false; scanner.close(); break; } } } }).start(); // 主循环直接启动,不需要提前等输入 do { // 生成随机数 for (int i = 0; i < randNumber.length; i++) { randNumber[i] = rand.nextInt(100); } // 打印相邻数对比 for (int i = 0; i < randNumber.length - 1; i++) { if (randNumber[i] < randNumber[i + 1]) { System.out.printf("Number %d smaller than %d%n", randNumber[i], randNumber[i + 1]); } else if (randNumber[i] > randNumber[i + 1]) { System.out.printf("Number %d greater than %d%n", randNumber[i], randNumber[i + 1]); } else { System.out.printf("Number %d equal to %d%n", randNumber[i], randNumber[i + 1]); } } } while (isRunning); } }
纯while循环实现
不需要do-while的话,只要把do-while的结构换成普通while即可,核心逻辑没有变化:
import java.util.Random; import java.util.Scanner; public class Main { private static volatile boolean isRunning = true; public static void main(String[] args) { Random rand = new Random(); int[] randNumber = new int[100]; // 输入监听线程和之前一致 new Thread(() -> { Scanner scanner = new Scanner(System.in); while (isRunning) { if (scanner.hasNext()) { char input = scanner.next().charAt(0); if (input == 'c') { isRunning = false; scanner.close(); break; } } } }).start(); // 直接用while判断运行标志,循环一启动就会跑 while (isRunning) { for (int i = 0; i < randNumber.length; i++) { randNumber[i] = rand.nextInt(100); } for (int i = 0; i < randNumber.length - 1; i++) { if (randNumber[i] < randNumber[i + 1]) { System.out.printf("Number %d smaller than %d%n", randNumber[i], randNumber[i + 1]); } else if (randNumber[i] > randNumber[i + 1]) { System.out.printf("Number %d greater than %d%n", randNumber[i], randNumber[i + 1]); } else { System.out.printf("Number %d equal to %d%n", randNumber[i], randNumber[i + 1]); } } } } }
如果要写纯无限循环的写法,也可以把循环条件换成while(true),在输入监听线程检测到c的时候修改运行标志位控制退出。要注意break只能跳出当前线程的循环,没法从子线程直接控制主循环退出,所以必须配合共享标志位实现。
内容的提问来源于stack exchange,提问作者dtaskin
相关产品推荐
相关产品推荐

