【问题标题】:How does these sleeping threads work?这些休眠线程是如何工作的?
【发布时间】:2014-01-26 16:14:46
【问题描述】:

我在试图弄清楚下面的代码如何工作时遇到了一些问题。在输出中,我得到所有线程都说它们处于休眠状态,然后 Thread-1 或 Thread-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.");
    }
}

【问题讨论】:

  • 我想我至少应该投赞成票,我试图告诉你主线程是执行的线程.. =)
  • 一般原则:如果您有一个 wait 没有围绕它的 while 循环来检查条件,那么您(几乎)肯定有一个等待发生的错误。
  • 谢谢!我需要 dem 点。
  • 您将wakeUpwakeupAll 方法添加到 Thread 对象的方法导致您感到困惑。您不会告诉特定线程唤醒——而是,lock.notify() 告诉 一个 等待线程唤醒(哪个线程取决于 JVM)。但是您的代码编写方式,似乎就像您打算告诉特定的 SleepingThreads 实例唤醒。

标签: java multithreading


【解决方案1】:

两件事:

  1. wakeUp()wakeUpAll() 方法在 threads[5] instance 上被调用,但不是它的执行 thread。它们在 main 线程上被调用。因此,即使threads[5] 线程 处于睡眠状态,您也可以调用它。

  2. main 必须休眠 200ms 的原因是因为如果它不休眠,一些线程(那些没有说“但现在我醒来”的线程还没有启动,当你调用wakeUpAll()(即,他们还没有执行run 方法,或者他们还没有到达lock.wait())。因此notifyAll() 发生在之前他们打电话给lock.wait(),等待后永远不会收到通知。

【讨论】:

  • 好吧,只有少数人说他们醒了,因为他们甚至在进入等待设置之前就收到了通知?
  • 是的,那些说“但现在我醒了”的人在调用 wakeUpAll() 之前等待。那些没有说“但现在我醒了”的人在调用 wakeUpAll() 之后等待。线程执行顺序并不总是可预测的。
【解决方案2】:

线程 5 没有调用 .wakeUp(),主线程正在调用 .wakeUp()

【讨论】:

  • 如果他们都死了,run() 方法怎么能完成?因为确实如此:所有线程都说他们醒来了。无论如何,这个答案并不能解释我观察到的行为。
  • 为什么主线程成功调用wakeUp()而不是wakeUpAll()
  • 查看我的回答,main 确实成功调用了wakeUpAll(),并在锁上执行了 notifyAll(),但这发生在 之前您的一些线程正在等待锁。因此,那些等待 后调用 wakeUpAll() 的线程永远不会看到 notifyAll()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 2015-01-17
  • 1970-01-01
  • 2011-09-11
  • 1970-01-01
相关资源
最近更新 更多