为何循环中可用相同变量名创建线程对象,即便线程不同时终止?
问题本质核心:局部引用变量的生命周期 ≠ 线程对象/内核线程的生命周期
你给出的代码可以正常运行,核心是要区分三层完全独立的逻辑:
for (int i = 0; i < 10; i++) { MyFirstThread thread = new MyFirstThread(); thread.start(); }
1. 栈上局部变量的作用域规则
你一开始的理解是对的:循环内部声明的thread是局部引用变量,存储在当前方法的栈帧的局部变量表中,作用域仅覆盖单次循环迭代:
- 每次进入迭代,会创建一个新的
thread引用变量 - 迭代结束后,这个引用变量立刻超出作用域失效,下一轮迭代会重新创建同名的新引用变量,二者不存在冲突
- 注意:这里被销毁的只是「存了对象内存地址的引用变量」,不是它指向的堆上的
Thread对象。
2. 堆上Thread对象的生命周期
new MyFirstThread()创建的线程对象存储在JVM堆内存中,只要存在强引用指向它,就不会被GC回收:
- 你调用
thread.start()时,JVM的线程调度器会直接持有这个Thread对象的强引用,用来跟踪线程状态、调度执行 - 此时哪怕栈上的
thread引用变量失效了,堆上的Thread对象因为被JVM调度器持有强引用,仍然会存活,完全不受局部引用销毁的影响 - 直到线程运行终止(
run()方法执行完成、或抛出未捕获的异常结束),JVM调度器才会释放对这个Thread对象的强引用,后续该对象才会被GC回收。
3. 操作系统内核线程的调度逻辑
JVM的Thread对象和操作系统的内核线程是一一绑定的:
- 调用
start()后操作系统会创建对应的内核线程,由OS独立调度执行,不会受Java局部变量生命周期的任何影响 - 内核线程会一直运行直到任务执行完成,不管Java层的引用变量是否存在。
内容的提问来源于stack exchange,提问作者Ingvar Kokorin
相关产品推荐
相关产品推荐

