Java线程状态转换,WAITING到BLOCKED,还是RUNNABLE?

16 浏览
0 Comments

Java线程状态转换,WAITING到BLOCKED,还是RUNNABLE?

SO的共识与互联网上几乎所有Java线程状态图之间似乎存在差异,特别是在调用notify()或notifyAll()后线程状态从WAITING转变的问题上...

  • WAITING从不直接转变为RUNNABLE
  • 线程在等待被通知之前一直处于WAITING状态...然后它变成BLOCKED...
  • 一旦线程被通知,它将不会变为可运行状态...这是...阻塞状态。

因此,在SO上的共识是:在调用notify()或notifyAll()之后,线程从WAITING转变为BLOCKED;下面的图示说明了这种转变(用绿色表示)。

问题

为什么大多数网上的状态图将从WAITING到RUNNABLE的转变,而不是BLOCKED?红色的描绘显示了错误的转变;我是否遗漏了什么?

0
0 Comments

最近我一直在关注这个问题。

根据Oracle文档Thread.State,我们可以使用LockSupport.park()将当前线程置于'WAITING'或'TIMED_WAITING'状态。

所以当你尝试LockSupport.unpark()时,指定的线程将从'WAITING'/'TIMED_WAITING'状态返回到'RUNNABLE'状态。(我不确定它是否会经过'BLOCKED'状态)

我认为LockSupport.unpark()会导致指定线程的状态直接从WAITING变为RUNNABLE。

0
0 Comments

Java中的线程状态转换问题:WAITING to BLOCKED, or RUNNABLE?

在Java中,线程状态的转换是非常重要的。有时候,我们可能会遇到一个问题:为什么一个线程从WAITING状态变为RUNNABLE状态,而不是BLOCKED状态?这个问题的答案其实很简单:当一个线程从WAITING状态被唤醒时,它需要重新获取等待对象的监视器锁,这就是为什么它会进入BLOCKED状态。

根据Java官方文档中的说明,一个处于BLOCKED状态的线程是因为它正在等待获取一个监视器锁,以进入一个同步的代码块/方法,或者在调用Object.wait()方法后重新进入同步的代码块/方法。

这个问题在Java官方文档中也有详细的解释。在Object.notify()方法的文档中,它明确说明了“当一个线程被唤醒后,它将无法继续执行,直到当前线程释放该对象上的锁”。同样,在Object.wait()方法的文档中也明确说明了“线程会等待,直到重新获取到监视器的所有权,并且恢复执行”。

这样解释起来是有道理的。但是,对于TIMED_WAITING状态来说,也是这样吗?除非它是通过sleep(t)方法进入了TIMED_WAITING状态。

根据Java官方文档中Thread.State的说明,WAITING状态适用于没有参数的Object.wait()方法,而TIMED_WAITING状态适用于接受等待时间参数的重载方法。这对于两种情况都适用。至于sleep方法,线程在唤醒时并不会释放任何持有的监视器锁,它仍然拥有它们。

当一个线程被唤醒时,它需要重新获取等待对象的监视器锁,这将使线程进入BLOCKED状态。这是Java中线程状态转换的一个重要原则。了解这个原则有助于我们更好地理解线程的运行机制,并能够更好地编写多线程的程序。

解决这个问题的方法是确保在使用notify方法唤醒线程之前,当前线程释放了等待对象的监视器锁。这样,被唤醒的线程就能够重新获得监视器的所有权,并继续执行。这样,线程的状态就会正确地从WAITING转换为BLOCKED或RUNNABLE。

希望本文对于理解Java线程状态转换的原因和解决方法有所帮助。通过深入学习和理解线程的运行机制,我们可以更好地编写高效、可靠的多线程程序。

0
0 Comments

一个线程处于WAITING状态,直到通过notify获得监视器并变为RUNNABLE状态,才会进入BLOCK状态。

对于TIMEDWAITING状态同样适用,如果监视器已被其他线程持有,则即使指定的时间已经过去,线程仍然会进入BLOCK状态。

问题的原因是线程在等待某个条件满足时,被阻塞在了WAITING或TIMEDWAITING状态。当条件满足时,线程需要获得监视器才能继续执行,因此进入了BLOCK状态。解决方法是通过notify或notifyAll来唤醒等待的线程,使其获得监视器并进入RUNNABLE状态。

下面是一个简单的示例代码,演示了线程从WAITING状态到BLOCK状态再到RUNNABLE状态的过程:

public class ThreadStateTransitionExample {
    private static final Object monitor = new Object();
    public static void main(String[] args) {
        Thread waitingThread = new Thread(() -> {
            synchronized (monitor) {
                try {
                    System.out.println("Thread is waiting");
                    monitor.wait(); // 线程进入WAITING状态
                    System.out.println("Thread is running again");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread blockingThread = new Thread(() -> {
            synchronized (monitor) {
                System.out.println("Thread is holding the monitor");
                try {
                    Thread.sleep(2000); // 模拟持有监视器的时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        waitingThread.start();
        blockingThread.start();
        try {
            Thread.sleep(1000); // 等待一段时间,确保blockingThread先持有监视器
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (monitor) {
            monitor.notify(); // 唤醒等待的线程
        }
    }
}

运行上述代码,可以看到输出结果为:

Thread is waiting
Thread is holding the monitor
Thread is running again

这表明线程首先进入WAITING状态,然后由于监视器被另一个线程持有而进入BLOCK状态。最后,通过notify方法唤醒等待的线程,使其重新进入RUNNABLE状态。

,当线程在等待某个条件满足时被阻塞在WAITING或TIMEDWAITING状态时,如果条件满足,线程需要获得监视器才能继续执行,因此会进入BLOCK状态。解决方法是通过notify或notifyAll来唤醒等待的线程,使其获得监视器并进入RUNNABLE状态。

0