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

Java守护线程控制用户线程终止问题求助

Java并发程序问题修复方案

问题根源

  1. 守护线程阻塞无法自动终止:scanner.nextLine()是阻塞式IO操作,即便主线程和所有Ball线程都执行完毕,JVM会等待该IO操作完成才会终止,因为操作系统层面的阻塞IO不会被JVM主动中断。
  2. 主线程逻辑判断时机错误:启动守护线程后立刻判断on变量,此时on必然为true,导致无论后续是否输入STOP,主线程都会先执行join逻辑,无法及时响应终止命令。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:43:22