Java 这些睡眠线程是如何工作的?

Java 这些睡眠线程是如何工作的?,java,multithreading,Java,Multithreading,我在试图弄清楚下面的代码是如何工作的时遇到了一些问题。在输出中,我得到所有线程都表示它们处于休眠状态,然后线程1或线程0被唤醒,程序冻结 我知道Thread-1或Thread-0被唤醒是因为threads[5]调用了notify()函数,所以等待集中的第一个线程恢复了生命。但是如果threads[5]中的线程因为调用了wait()而被阻塞,它怎么还能调用wakeUp()函数呢 如果它可以调用方法,为什么wakeUpAll()函数不起作用?如果我在主线程上睡觉,为什么它会起作用 public cl

我在试图弄清楚下面的代码是如何工作的时遇到了一些问题。在输出中,我得到所有线程都表示它们处于休眠状态,然后线程1或线程0被唤醒,程序冻结

我知道Thread-1或Thread-0被唤醒是因为
threads[5]
调用了
notify()
函数,所以等待集中的第一个线程恢复了生命。但是如果
threads[5]
中的线程因为调用了
wait()
而被阻塞,它怎么还能调用
wakeUp()
函数呢

如果它可以调用方法,为什么
wakeUpAll()
函数不起作用?如果我在主线程上睡觉,为什么它会起作用

public class SleepingThreads extends Thread
{
    Object lock;

    public SleepingThreads(Object l) { lock=l; }

    public void run()
    {
        System.out.println(this.getName()+" said: I am sleepy...");
        synchronized(lock)
        {
            try { lock.wait(); } catch (InterruptedException e){}
            System.out.println(this.getName()+" said: but now I woke up...");
        }
    }

   public void wakeUp() { synchronized (lock) { lock.notify(); } }

   public void wakeUpAll() { synchronized (lock) { lock.notifyAll(); } }

    public static void main(String[] args) throws InterruptedException
    {
        Object lock = new Object();
        SleepingThreads[] threads = new SleepingThreads[10];

        for (int i=0; i<10;i++)
        {
            threads[i] = new SleepingThreads(lock); 
            threads[i].start();
        }

        threads[5].wakeUp();
        //currentThread().sleep(200);
        threads[5].wakeUpAll();

        System.out.println("Done.");
    }
}
公共类SleepingThreads扩展线程
{
对象锁;
公共睡眠线程(对象l){lock=l;}
公开募捐
{
System.out.println(this.getName()+“说:我困了…”);
已同步(锁定)
{
尝试{lock.wait();}catch(InterruptedException e){}
System.out.println(this.getName()+“说:但是现在我醒了…”);
}
}
public void wakeUp(){synchronized(lock){lock.notify();}}
public void wakeUpAll(){synchronized(lock){lock.notifyAll();}}
公共静态void main(字符串[]args)引发InterruptedException
{
对象锁=新对象();
SleepingThreads[]threads=新的SleepingThreads[10];

对于(int i=0;i线程5没有调用.wakeUp(),主线程正在调用.wakeUp()

两件事:

  • wakeUp()
    wakeUpAll()
    方法正在
    threads[5]
    实例上调用,但不是在其执行线程上调用。它们正在主线程上调用。因此,即使
    threads[5]
    线程处于休眠状态,也可以调用它

  • main
    必须睡眠200ms的原因是,如果没有睡眠,一些线程(当您调用
    wakeUpAll()
    时,没有说“但是现在我醒了”的线程还没有启动(即,要么它们还没有执行
    run
    方法,要么它们还没有锁定
    wait()
    )。因此,
    notifyAll()
    在调用
    lock.wait()
    之前发生,并且在等待之后,它们永远不会收到通知


  • 如果它们都死了,
    run()
    方法怎么能结束呢?因为它是这样的:所有线程都说它们醒了。无论如何,这个答案并不能解释我观察到的行为。为什么主线程成功地调用了
    wakeUp()
    ,但没有调用
    wakeUpAll()
    ?看到我的答案,main成功地调用了wakeUpAll(),并且没有调用notifyAll()在锁上,但这发生在某些线程等待锁之前。因此,那些在调用wakeUpAll()之后等待的线程永远不会看到notifyAll()。好的,所以只有少数线程,说他们醒来是因为他们在进入等待集之前收到通知?是的,那些说“但是现在我醒来了”的线程在wakeUpAll之前等待()被调用。那些没有说“但是现在我醒了”的线程在wakeUpAll()被调用后等待。线程执行顺序并不总是可预测的。我想我至少应该获得一个向上投票,我正试图告诉您,主线程是执行的线程….=)一般原则:如果你有一个
    wait
    ,没有一个while循环来检查条件,你(几乎)保证有一个bug正在等待发生。谢谢!我需要dem点。您向Thread对象添加
    wakeUp
    wakeupAll
    方法的做法会让您感到困惑。您不会告诉特定的线程要唤醒,而是,
    lock.notify()
    告诉一个等待唤醒的线程(JVM正在唤醒哪个线程).但从编写代码的方式来看,您似乎打算让特定的
    SleepingThreads
    实例醒来。