为什么在thread.join之后线程不处于TERMINATED状态?

时间:2018-10-16 07:32:53

标签: multithreading scala

我有此代码段,在线程完成后,我在其中检查线程的状态。

import java.lang.management.ManagementFactory

import scala.concurrent.ExecutionContext
import scala.collection.JavaConversions._
import scala.collection.JavaConverters.asScalaSetConverter
import scala.concurrent.duration.{Duration, SECONDS}


object ThreadUsage2 {

  def main(args: Array[String]): Unit = {

    println("Main thread" + Thread.currentThread().getName())
    val ex = ExecutionContext.Implicits.global

    var threadName = ""
    val sleepTask = new Thread(() => {

      threadName = Thread.currentThread().getName()
      println("Executing Thread task :" + Thread.currentThread().getName())
      Thread.sleep(5000)
      println("Thread  finished :" + Thread.currentThread().getName())
    })

    ex.execute(sleepTask)

    sleepTask.join()
    Thread.sleep(10000)

    println("Now the sleep task is in state" + sleepTask.getState)


    val running = Thread.getAllStackTraces.keySet()

    running.asScala.toSet[Thread].foreach(a => {

      if (a.getName.matches(threadName)) {

        println(" thread with name " + threadName + " is in state " + a.getState)

      }
    })

  }
}

我看到的输出令人困惑。我希望线程处于TERMINATED状态。我在两个印刷品中看到了两个不同的状态。 输出:

Main threadmain Executing Thread task :scala-execution-context-global-12 Thread finished :scala-execution-context-global-12 Now the sleep task is in stateNEW thread with name scala-execution-context-global-12 is in state TIMED_WAITING

出现上述线程状态的原因是什么?

2 个答案:

答案 0 :(得分:2)

@Yaneeve已诊断出问题:您的sleepTask线程从未真正启动。

但是为什么join返回尚未开始的Thread

javadoc对此进行了解释。

  

此实现使用以this.wait为条件的this.isAlive调用循环。当线程终止时,将调用this.notifyAll方法。建议应用程序不要在线程实例上使用waitnotifynotifyAll

由于线程启动时isAlive首先成为true,因此上述含义意味着“加入”尚未启动的线程将立即成功。这种(种类)与javadoc的前一句矛盾,该句指出:

  

此线程死亡最多等待millis毫秒。

但是很明显,这就是实现的行为方式...

答案 1 :(得分:1)

execute收到Runnable

/** Runs a block of code on this execution context.
 *
 *  @param runnable  the task to execute
 */
def execute(runnable: Runnable): Unit

因此执行者只关心您提供的代码块:

   () => {
          threadName = Thread.currentThread().getName()
          println("Executing Thread task :" + Thread.currentThread().getName())
          Thread.sleep(5000)
          println("Thread  finished :" + Thread.currentThread().getName())
        }

那是因为Thread Runnable

class Thread implements Runnable

因此,sleepTask.join()是即时的,因为您创建的线程从未处于活动状态,因为您从未启动过它。

显然,将ex.execute(sleepTask)更改为sleepTask.start()会得到您所期望的TERMINATED状态,但是我感觉这并不是您最初想要做的事情