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

Scala 3中含for循环的线程无法调用join的异常问题

Scala 3中object extends App结合线程、join与集合遍历的异常问题

问题现象

在Scala 3里,当你写了一个继承App的object,里面启动新线程,线程的run方法用for循环或者集合foreach,同时主线程调用t.join()时,会出现诡异异常:线程能打印Started,但循环及之后的代码完全不执行。只要注释掉for循环或者join()任意一个,代码就正常运行。

更具体的细节:

  • 把for循环换成while遍历迭代器,代码能正常打印;
  • 把循环逻辑放到单独的类里、用REPL运行、用@main注解的脚本、或者在Scala 2里跑同样的代码,都没问题;
  • 如果把join()换成Thread.sleep(3000),新线程的循环要等主线程休眠结束才会开始执行。

问题代码示例:

object Main extends App {
  val t = new Thread() {
    override def run() = {
      println("Started")
      for (j <- 1 to 2) {println("Work")}
    }
  }
  t.start()
  t.join()
}

补充测试:

  • 换成集合foreach同样失效:
val it = List(1, 2, 3)
it.foreach(x => println(x))
  • 但用while遍历迭代器却正常:
val it = List(1, 2, 3).iterator
while(it.hasNext) println(it.next())

问题根源

这是Scala 3对App特质的实现机制导致的:
Scala 3的App用了延迟初始化的改进逻辑,继承App的object里的代码会被包装到一个特殊的初始化方法中,而不是直接在主线程的main方法里执行。当主线程调用t.join()阻塞时,App的初始化流程还没走完,集合类(比如Range、List)的加载/初始化会被主线程的阻塞卡住——新线程要用到这些集合类,但它们的初始化依赖主线程完成某些步骤,于是就出现了类似死锁的阻塞,导致循环代码无法执行。

而while循环直接操作迭代器,不需要触发那些被阻塞的集合类初始化逻辑;换成@main、单独类或者Scala 2的App,代码是直接在标准的main方法里执行,不存在这个初始化阻塞的问题。

解决办法

有三种简单的修复方式:

1. 改用@main注解替代extends App

这是Scala 3推荐的启动方式,完全避开App的初始化问题:

@main def main(): Unit = {
  val t = new Thread() {
    override def run() = {
      println("Started")
      for (j <- 1 to 2) {println("Work")}
    }
  }
  t.start()
  t.join()
}

2. 将线程逻辑放到独立类中

把线程的run方法逻辑移到单独的类里,避免和App的初始化逻辑纠缠:

object Main extends App {
  class WorkerThread extends Thread {
    override def run() = {
      println("Started")
      for (j <- 1 to 2) {println("Work")}
    }
  }
  
  val t = new WorkerThread()
  t.start()
  t.join()
}

3. 手动实现main方法

直接写标准的main方法,绕过App特质的逻辑:

object Main {
  def main(args: Array[String]): Unit = {
    val t = new Thread() {
      override def run() = {
        println("Started")
        for (j <- 1 to 2) {println("Work")}
      }
    }
    t.start()
    t.join()
  }
}

内容的提问来源于stack exchange,提问作者Lox

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 17:07:40