How to use wait and notify in Java without IllegalMonitorStateException?

后端 未结 12 2129
后悔当初
后悔当初 2020-11-22 02:21

I have 2 matrices and I need to multiply them and then print the results of each cell. As soon as one cell is ready I need to print it, but for example I need to print the [

相关标签:
12条回答
  • 2020-11-22 03:12

    While using the wait and notify or notifyAll methods in Java the following things must be remembered:

    1. Use notifyAll instead of notify if you expect that more than one thread will be waiting for a lock.
    2. The wait and notify methods must be called in a synchronized context. See the link for a more detailed explanation.
    3. Always call the wait() method in a loop because if multiple threads are waiting for a lock and one of them got the lock and reset the condition, then the other threads need to check the condition after they wake up to see whether they need to wait again or can start processing.
    4. Use the same object for calling wait() and notify() method; every object has its own lock so calling wait() on object A and notify() on object B will not make any sense.
    0 讨论(0)
  • 2020-11-22 03:16

    To be able to call notify() you need to synchronize on the same object.

    synchronized (someObject) {
        someObject.wait();
    }
    
    /* different thread / object */
    synchronized (someObject) {
        someObject.notify();
    }
    
    0 讨论(0)
  • 2020-11-22 03:16

    we can call notify to resume the execution of waiting objects as

    public synchronized void guardedJoy() {
        // This guard only loops once for each special event, which may not
        // be the event we're waiting for.
        while(!joy) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        System.out.println("Joy and efficiency have been achieved!");
    }
    

    resume this by invoking notify on another object of same class

    public synchronized notifyJoy() {
        joy = true;
        notifyAll();
    }
    
    0 讨论(0)
  • 2020-11-22 03:17

    Let's say you have 'black box' application with some class named BlackBoxClass that has method doSomething();.

    Further, you have observer or listener named onResponse(String resp) that will be called by BlackBoxClass after unknown time.

    The flow is simple:

    private String mResponse = null; 
     ...
    BlackBoxClass bbc = new BlackBoxClass();
       bbc.doSomething();
    ...
    @override
    public void onResponse(String resp){        
          mResponse = resp;       
    }
    

    Lets say we don't know what is going on with BlackBoxClass and when we should get answer but you don't want to continue your code till you get answer or in other word get onResponse call. Here enters 'Synchronize helper':

    public class SyncronizeObj {
    public void doWait(long l){
        synchronized(this){
            try {
                this.wait(l);
            } catch(InterruptedException e) {
            }
        }
    }
    
    public void doNotify() {
        synchronized(this) {
            this.notify();
        }
    }
    
    public void doWait() {
        synchronized(this){
            try {
                this.wait();
            } catch(InterruptedException e) {
            }
        }
    }
    }
    

    Now we can implement what we want:

    public class Demo {
    
    private String mResponse = null; 
     ...
    SyncronizeObj sync = new SyncronizeObj();
    
    public void impl(){
    
    BlackBoxClass bbc = new BlackBoxClass();
       bbc.doSomething();
    
       if(mResponse == null){
          sync.doWait();
        }
    
    /** at this momoent you sure that you got response from  BlackBoxClass because
      onResponse method released your 'wait'. In other cases if you don't want wait too      
      long (for example wait data from socket) you can use doWait(time) 
    */ 
    ...
    
    }
    
    
    @override
    public void onResponse(String resp){        
          mResponse = resp;
          sync.doNotify();       
       }
    
    }
    
    0 讨论(0)
  • 2020-11-22 03:21

    Simple use if you want How to execute threads alternatively :-

    public class MyThread {
        public static void main(String[] args) {
            final Object lock = new Object();
            new Thread(() -> {
                try {
                    synchronized (lock) {
                        for (int i = 0; i <= 5; i++) {
                            System.out.println(Thread.currentThread().getName() + ":" + "A");
                            lock.notify();
                            lock.wait();
                        }
                    }
                } catch (Exception e) {}
            }, "T1").start();
    
            new Thread(() -> {
                try {
                    synchronized (lock) {
                        for (int i = 0; i <= 5; i++) {
                            System.out.println(Thread.currentThread().getName() + ":" + "B");
                            lock.notify();
                            lock.wait();
                        }
                    }
                } catch (Exception e) {}
            }, "T2").start();
        }
    }
    

    response :-

    T1:A
    T2:B
    T1:A
    T2:B
    T1:A
    T2:B
    T1:A
    T2:B
    T1:A
    T2:B
    T1:A
    T2:B
    
    0 讨论(0)
  • 2020-11-22 03:26

    You can only call notify on objects where you own their monitor. So you need something like

    synchronized(threadObject)
    {
       threadObject.notify();
    }
    
    0 讨论(0)
提交回复
热议问题