Java守护线程控制用户线程终止问题求助
Java并发程序问题修复方案
问题根源
- 守护线程阻塞无法自动终止:
scanner.nextLine()是阻塞式IO操作,即便主线程和所有Ball线程都执行完毕,JVM会等待该IO操作完成才会终止,因为操作系统层面的阻塞IO不会被JVM主动中断。 - 主线程逻辑判断时机错误:启动守护线程后立刻判断
on变量,此时on必然为true,导致无论后续是否输入STOP,主线程都会先执行join逻辑,无法及时响应终止命令。 - Ball线程逻辑冗余:每个Ball只需完成一次跳跃,但原代码在跳完后仍持续循环抢锁检查标志,浪费CPU资源。
修复后的代码
Ball.java
public class Ball extends Thread { public int id; public static volatile boolean stopFlag = false; public static final Object lock = new Object(); // 用final保证锁对象不可变 public Ball(int id) { this.id = id; } // 统一停止所有Ball线程的方法 public static void stopAll() { stopFlag = true; synchronized (lock) { lock.notifyAll(); // 唤醒所有等待锁的线程 } } @Override public void run() { synchronized (lock) { if (stopFlag) { return; } System.out.println("Ball " + id + " jumping..."); try { Thread.sleep(1000); } catch (InterruptedException e) { // 被中断时直接退出线程 return; } } // 跳跃完成后直接结束线程,无需循环 } }
Test.java
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Test { public static void main(String args[]) { List<Ball> balls = new ArrayList<>(); for (int i = 0; i < 50; i++) { balls.add(new Ball(i)); } for (Ball ball : balls) { ball.start(); } // 输入监听线程 Thread inputThread = new Thread(() -> { Scanner scanner = new Scanner(System.in); try { String input = scanner.nextLine().toUpperCase(); if (input.equals("STOP")) { Ball.stopAll(); System.out.println("Jumping aborted"); } } catch (IllegalStateException e) { // System.in被关闭时触发,直接退出 } finally { scanner.close(); } }); inputThread.setDaemon(true); inputThread.start(); // 等待所有Ball线程执行完成 boolean allFinished = true; for (Ball ball : balls) { try { ball.join(); } catch (InterruptedException e) { // 被中断说明收到STOP命令,标记未全部完成 allFinished = false; } } // 强制终止输入线程的阻塞状态 inputThread.interrupt(); try { System.in.close(); } catch (Exception e) { e.printStackTrace(); } if (allFinished) { System.out.println("All balls have jumped"); } } }
关键修改说明
- Ball类优化:移除无用的while循环,完成一次跳跃后直接结束线程;提供统一的
stopAll方法,设置停止标志并唤醒所有等待线程。 - Test类优化:移除冗余的
on变量,通过join的中断状态判断是否被STOP终止;所有Ball线程完成后,主动中断输入线程并关闭System.in,强制终止阻塞的IO操作;简化输入线程逻辑,只需处理一次输入命令。
内容的提问来源于stack exchange,提问作者Anonimni Gost
相关产品推荐
相关产品推荐

