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

调用内部启动线程的Java方法会阻塞等待线程执行完吗?

核心结论

两种写法并不等价,Java中不存在「调用内部启动新线程的方法时,会隐式等待内部线程执行完毕才返回」的机制。Thread.start()本身是异步方法,调用后会立刻返回,不会阻塞发起调用的线程。

第一种写法的执行逻辑

你的第一版代码实际执行顺序如下:

// things A
method();
// things B

public void method(){
 new Thread(() -> {
    // slow stuff (慢文件写入逻辑)
 }).start();
}
  1. 当前调用线程先执行things A的全部逻辑
  2. 进入method()方法,完成线程对象创建、调用start()通知JVM为新线程分配栈内存、初始化线程上下文、纳入系统调度
  3. start()调用完成后立刻退出method(),回到调用点
  4. 当前线程马上开始执行things B,和新启动的子线程完全并行,互不阻塞

你观察到的「执行完things A后等待一段时间才执行things B」,本质是线程创建本身的固定开销导致的,并不是在等待子线程的慢写入任务跑完:JVM向操作系统申请线程资源、初始化线程上下文、第一次触发文件IO时的类加载、文件句柄申请都有少量耗时,刚好落在method()调用的时间窗口里,才给你造成了阻塞等待慢任务的错觉。实际上method()返回的时间点远早于子线程慢写入任务完成的时间点,things B不需要等慢写入跑完就会执行。

第二种写法的执行逻辑

第二版代码的执行顺序如下:

// things A
new Thread(() -> {
    method();
}).start();
// things B

public void method(){
    // slow stuff (慢文件写入逻辑)
}
  1. 当前调用线程先执行things A的全部逻辑
  2. 创建包装了method()调用的线程对象,调用start()触发线程初始化,这一步完成后立刻返回
  3. 当前线程马上开始执行things B
  4. 新启动的子线程独立执行method()里的慢写入逻辑,和当前线程并行

两种写法的核心差异

  • 第一版中,线程创建、初始化的动作是在原调用线程中执行的,这部分固定开销会占用原线程的执行时间,开销结束后原线程才会运行things B
  • 第二版中,线程对象创建、method()调用、慢写入执行的全流程都在新线程中完成,原线程仅需要执行极少量的线程对象构造、start()调用逻辑就会立刻往下走,触发things B的延迟会比第一版更低
  • 两版写法的慢写入任务都不会阻塞原线程执行things B。如果需要显式等待子线程任务执行完成再往下走,必须手动调用Thread.join()、Future.get()这类阻塞等待方法,否则Java不会自动做跨线程的等待。

如果你实际测试时发现第一版的things B确实是在慢写入任务完全结束后才开始执行,需要排查代码里的隐式同步逻辑:比如慢写入任务和things B争抢同一把锁、用了同步IO触发了系统级的资源阻塞、或者写入逻辑里调用了阻塞原线程的方法,和「方法内部启动线程」这个写法本身没有关系。

内容的提问来源于stack exchange,提问作者Ángel Fas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 09:15:40