Что, если я жду на объекте, который не является Runnable? - PullRequest
1 голос
/ 25 января 2012

Рассмотрим следующий код: -

public class UsingWait1{
public static void main(String... aaa){
    CalculateSeries r = new CalculateSeries();
    Thread t = new Thread(r);
    t.start();
    synchronized(r){
        try{
            r.wait();   //Here I am waiting on an object which is Runnable. So from its run method, it can notify me (from inside a synchronized block).
        } catch (InterruptedException e) {
            System.out.println("Interrupted");
        }

    }
    System.out.println(r.total);
    try{
        Thread.sleep(1);
    } catch (InterruptedException e){
        System.out.println("Interrupted");
    }
    System.out.println(r.total);

}
}

class CalculateSeries implements Runnable{
int total;
public void run(){
synchronized(this){
    for(int i = 1; i <= 10000; i++){
        total += i;
    }
    notify();   // Line 1 .. Notify Exactly one of all the threads waiting on this instance of the class to wake up
}
}
}

Здесь я жду на CalculateSeries, которая является Runnable.Поэтому я могу уведомить ожидающий поток из метода run () в CalculateSeries.

Но теперь рассмотрим следующий код, в котором я ожидаю объект, который не является Runnable.

public class WaitNotOnThread{
public static void main(String... aaa){
    NotRunnable nr = new NotRunnable();
    IAmRunnable r = new IAmRunnable(nr);
    new Thread(r).start();
    synchronized(nr){
        try{
            nr.wait();
        } catch(InterruptedException e){
            System.out.println("Wait interrupted");             
        }

        System.out.println("After being notified within synchronized");
    }
    System.out.println("After synchronized");
}
}

class IAmRunnable implements Runnable{
NotRunnable nr;
IAmRunnable(NotRunnable nr){
    this.nr = nr;
}
public void run(){
    synchronized(nr){
        try{
            Thread.sleep(1000);
        } catch(InterruptedException e){
            System.out.println("Sleeping Interrupted :( ");
        }
        notify();                  // Line 2
    }
}
}

class NotRunnable{
}

Здесь я получаю IllegalMonitorStateException в строке 2. Я жду одного и того же экземпляра объекта (который не является Runnable) при вызове обоих, wait () и notify ().Тогда в чем проблема?

Может ли кто-нибудь также привести некоторые сценарии, в которых было бы полезно ожидать объект, который не является Runnable ??

1 Ответ

4 голосов
/ 25 января 2012

Ждать не обязательно на Runnable.Вот почему notify () включен Object , а не Runnable .Я предполагаю, что это помогает во всех случаях, когда мы хотим избежать занятого ожидания.

Проблема, похоже, заключается в том, что synchronized () находится на nr, а уведомление вызывается для другого объекта.Также должны быть синхронизированы конечные переменные.

class IAmRunnable implements Runnable {
     final NotRunnable nr;

    IAmRunnable( final NotRunnable nr) {
        this.nr = nr;
    }

    public void run() {
        synchronized (nr) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("Sleeping Interrupted :( ");
            }
            nr.notify();                  // Line 2
        }
    }
}
...