Java调用interrupt()后RAM监控线程仍持续打印内存占用的问题
问题原因
你现在的问题核心是调用错了interrupt方法:
- 主类里的
thread_RAM.interrupt()调用的是Java原生Thread类的interrupt(),它只会给线程打上中断标记,并不会触发你在RAMMonitor里自定义的interrupt()方法(也就是那个把isRunning设为false的方法)。 - 同时,
RAMMonitor的run()方法里,捕获InterruptedException后只是重新设置了中断标记,但没修改isRunning的值,所以while(isRunning)的循环条件一直为true,线程会无限跑下去。
修复方案
有两种靠谱的修复方式,选一种就行:
方案1:正确触发自定义的中断逻辑
修改主类的interruptMonitoring()方法,直接调用RAMMonitor实例的interrupt()方法,同时保留Thread的interrupt来唤醒sleep中的线程:
public void interruptMonitoring() { // 先调用自定义的interrupt,把isRunning设为false monitor_RAM.interrupt(); // 再调用Thread的interrupt,唤醒sleep中的线程,让它立刻检查循环条件 thread_RAM.interrupt(); try { thread_RAM.join(); } catch (InterruptedException e) { // 打印异常信息方便调试 e.printStackTrace(); } }
这样一来,sleep的线程会被唤醒,同时循环条件isRunning已经是false,循环会直接终止。
方案2:结合中断标记判断循环条件
如果不想依赖自定义的isRunning变量,也可以直接用线程的中断状态来控制循环,更符合Java线程中断的设计:
修改RAMMonitor的代码:
public class RAMMonitor implements Runnable { @Override public void run() { // 循环条件改为检查当前线程的中断状态 while (!Thread.currentThread().isInterrupted()) { long usedMemory = getUsedMemory(); long totalMemory = getTotalMemory(); double memoryUsage = (double) usedMemory / totalMemory * 100; System.out.println("RAM Usage -----> " + (int) memoryUsage + "%"); try { Thread.sleep(1000); } catch (InterruptedException e) { // 捕获异常后中断标记会被清除,重新设置标记 Thread.currentThread().interrupt(); } } } // 以下方法保持不变 private long getUsedMemory() { Runtime runtime = Runtime.getRuntime(); return runtime.totalMemory() - runtime.freeMemory(); } private long getTotalMemory() { Runtime runtime = Runtime.getRuntime(); return runtime.totalMemory(); } }
这种情况下,主类的interruptMonitoring()方法不需要修改,调用thread_RAM.interrupt()后,线程要么在sleep时被唤醒并重新设置中断标记,要么在下次循环时检测到中断状态,从而终止循环。
额外建议
- 不要空捕获
InterruptedException,至少打印异常栈信息,方便排查问题。 - 用
volatile修饰isRunning是正确的,保证了多线程下的变量可见性,这点你做的没问题。
内容的提问来源于stack exchange,提问作者Vertos
相关产品推荐
相关产品推荐

