Thread.isAlive() 检查后 Thread.start() 抛出异常

aws*_*kis 0 java multithreading

我正在研究 Java 中的多线程,并且遇到了一个奇怪的问题。

当我尝试使用调度程序启动一个新线程时Thread.start(),我了解到我们需要进行Thread.isAlive()检查,因为启动和恢复需要不同的进程。但是,此代码显示检查和start()

if ( current.isAlive( ) )
     current.setPriority( 4 );
else {
     // Spawn must be controlled by Scheduler
     // Scheduler must start a new thread
     current.start( );
     current.setPriority( 4 );
}
Run Code Online (Sandbox Code Playgroud)

其中 current 被保证是一个有效的线程。我最终遇到了这个错误

Exception in thread "Thread-0" java.lang.IllegalThreadStateException
        at java.base/java.lang.Thread.start(Thread.java:790)
        at Scheduler.run(Scheduler.java:152)
Run Code Online (Sandbox Code Playgroud)

start()这就是为什么我认为在不应该的情况下调用是一个问题。start()然而,从所有迹象来看,除非线程不活动,否则它不应该被调用。

因此,我的问题有两个:

  1. 上面的代码是否有问题,如果线程已经启动,则允许第二个块运行,并且

  2. 还有哪些其他问题可能会引发该异常?我看到在 中抛出了相同的异常setDaemon(),但是我没有调用它,所以这应该是无关紧要的。

And*_*eas 5

AThread有 a State,可通过调用 来检索getState()。javadoc 显示State

线程状态。线程可以处于以下状态之一:

  • NEW
    尚未启动的线程处于此状态。
  • RUNNABLE
    Java虚拟机中执行的线程就处于这种状态。
  • BLOCKED
    等待监视器锁而被阻塞的线程就处于这种状态。
  • WAITING
    无限期等待另一个线程执行特定操作的线程就处于此状态。
  • TIMED_WAITING
    等待另一个线程执行操作长达指定等待时间的线程就处于此状态。
  • TERMINATED
    已经退出的线程就处于这种状态。

线程在给定时间点只能处于一种状态。这些状态是虚拟机状态,不反映任何操作系统线程状态。

当您调用 时start(),线程将离开该NEW状态,并且永远不会再具有该状态。Javadocstart()说:

IllegalThreadStateException如果线程已经启动则抛出异常。

这意味着如果状态不是NEW

然而,javadocisAlive()说:

测试该线程是否存活。如果线程已启动且尚未死亡,则该线程处于活动状态。

这意味着该线程尚未NEW(已启动)且未TERMINATED(尚未死亡)

正如您所看到的,即使不是启动线程的有效状态,isAlive()也会返回 false 。TERMINATEDTERMINATED

如果您需要知道是否可以启动线程,请检查状态:

if (thread.getState() == Thread.State.NEW) {
    thread.start();
    // Ok, the thread is now beginning to work on it
} else if (thread.getState() != Thread.State.TERMINATED) {
    // Yay, the thread is working on it
} else {
    // Oops, what happened???
]
Run Code Online (Sandbox Code Playgroud)