2014-01-26 2 views
1

У меня возникли проблемы с попыткой выяснить, как работает код ниже. На выходе я получаю, что все потоки говорят, что они сонные, тогда либо 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."); 
    } 
} 
+0

Я думаю, что я должен хотя бы получить голос, я пытался сказать вам, что основной поток был тот, кто исполнил .. =) –

+1

Общий принцип: если у вас есть 'wait' без цикла while, чтобы проверить состояние, вы (почти) гарантированно ожидаете ошибку. – Voo

+0

спасибо! Мне нужны дем-очки. –

ответ

1

две вещи:

  1. wakeUp() и wakeUpAll() методы в настоящее время вызываются на threads[5]пример, но не его исполнение нить. Они вызывают на главной линии . Таким образом, вы можете это назвать, хотя нить спит.

  2. Причина main должен спать 200мс, потому что если это не так, некоторые из нитей (те, которые не говорят «но теперь я просыпался» еще не началась, когда вы звоните wakeUpAll() (то есть, либо они не выполнили метод run еще, или они еще не добрались до lock.wait() пока). Как таковой notifyAll() происходит перед тем они называют lock.wait(), и они никогда не уведомляется после ожидания.

+0

Хорошо, так что только некоторые из них, скажем, проснулись, потому что их уведомили, прежде чем они даже подошли к набору ожидания? – dabadaba

+0

Yup, те, кто сказал «но теперь я проснулся», ждали, пока не вызвана wakeUpAll(). Те, которые не говорят «но теперь я проснулся», ждали, когда вызвана wakeUpAll(). Порядок выполнения потока не всегда предсказуем. –

0

Тема 5 не называет .wakeUp(), основной поток вызывает .wakeUp()

+0

Если все они умирают, как может закончить метод 'run()'? Потому что это происходит: все потоки сказали, что они проснулись. Во всяком случае, этот ответ не объясняет поведение, которое я наблюдаю. – dabadaba

+0

Почему главный поток успешно вызывает 'wakeUp()', но не 'wakeUpAll()'? – dabadaba

+0

См. Мой ответ. Главное выполняет вызов wakeUpAll() и делает notifyAll() на блокировке, но это происходит * до того, как некоторые из ваших потоков ждут блокировки. Таким образом, те потоки, которые ждут * после * вызова wakeUpAll(), никогда не видят notifyAll(). –

Смежные вопросы