IllegalMonitorStateException on wait() call

后端 未结 10 1346
感动是毒
感动是毒 2020-11-22 11:37

I am using multi-threading in java for my program. I have run thread successfully but when I am using Thread.wait(), it is throwing java.lang.IllegalMonit

相关标签:
10条回答
  • 2020-11-22 11:46

    Since you haven't posted code, we're kind of working in the dark. What are the details of the exception?

    Are you calling Thread.wait() from within the thread, or outside it?

    I ask this because according to the javadoc for IllegalMonitorStateException, it is:

    Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.

    To clarify this answer, this call to wait on a thread also throws IllegalMonitorStateException, despite being called from within a synchronized block:

    
         private static final class Lock { }
         private final Object lock = new Lock();
    
        @Test
        public void testRun() {
            ThreadWorker worker = new ThreadWorker();
            System.out.println ("Starting worker");
            worker.start();
            System.out.println ("Worker started - telling it to wait");
            try {
                synchronized (lock) {
                    worker.wait();
                }
            } catch (InterruptedException e1) {
                String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
                System.out.println (msg);
                e1.printStackTrace();
                System.out.flush();
            }
            System.out.println ("Worker done waiting, we're now waiting for it by joining");
            try {
                worker.join();
            } catch (InterruptedException ex) { }
    
        }
    
    0 讨论(0)
  • 2020-11-22 11:48

    Those who are using Java 7.0 or below version can refer the code which I used here and it works.

    public class WaitTest {
    
        private final Lock lock = new ReentrantLock();
        private final Condition condition = lock.newCondition();
    
        public void waitHere(long waitTime) {
            System.out.println("wait started...");
            lock.lock();
            try {
                condition.await(waitTime, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            lock.unlock();
            System.out.println("wait ends here...");
        }
    
        public static void main(String[] args) {
            //Your Code
            new WaitTest().waitHere(10);
            //Your Code
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 11:52

    wait is defined in Object, and not it Thread. The monitor on Thread is a little unpredictable.

    Although all Java objects have monitors, it is generally better to have a dedicated lock:

    private final Object lock = new Object();
    

    You can get slightly easier to read diagnostics, at a small memory cost (about 2K per process) by using a named class:

    private static final class Lock { }
    private final Object lock = new Lock();
    

    In order to wait or notify/notifyAll an object, you need to be holding the lock with the synchronized statement. Also, you will need a while loop to check for the wakeup condition (find a good text on threading to explain why).

    synchronized (lock) {
        while (!isWakeupNeeded()) {
            lock.wait();
        }
    }
    

    To notify:

    synchronized (lock) {
        makeWakeupNeeded();
        lock.notifyAll();
    }
    

    It is well worth getting to understand both Java language and java.util.concurrent.locks locks (and java.util.concurrent.atomic) when getting into multithreading. But use java.util.concurrent data structures whenever you can.

    0 讨论(0)
  • 2020-11-22 11:58

    Thread.wait() call make sense inside a code that synchronizes on Thread.class object. I don't think it's what you meant.
    You ask

    How can I make a thread wait until it will be notified?

    You can make only your current thread wait. Any other thread can be only gently asked to wait, if it agree.
    If you want to wait for some condition, you need a lock object - Thread.class object is a very bad choice - it is a singleton AFAIK so synchronizing on it (except for Thread static methods) is dangerous.
    Details for synchronization and waiting are already explained by Tom Hawtin. java.lang.IllegalMonitorStateException means you are trying to wait on object on which you are not synchronized - it's illegal to do so.

    0 讨论(0)
  • 2020-11-22 12:00

    Not sure if this will help somebody else out or not but this was the key part to fix my problem in user "Tom Hawtin - tacklin"'s answer above:

    synchronized (lock) {
        makeWakeupNeeded();
        lock.notifyAll();
    }
    

    Just the fact that the "lock" is passed as an argument in synchronized() and it is also used in "lock".notifyAll();

    Once I made it in those 2 places I got it working

    0 讨论(0)
  • 2020-11-22 12:04

    I received a IllegalMonitorStateException while trying to wake up a thread in / from a different class / thread. In java 8 you can use the lock features of the new Concurrency API instead of synchronized functions.

    I was already storing objects for asynchronous websocket transactions in a WeakHashMap. The solution in my case was to also store a lock object in a ConcurrentHashMap for synchronous replies. Note the condition.await (not .wait).

    To handle the multi threading I used a Executors.newCachedThreadPool() to create a thread pool.

    0 讨论(0)
提交回复
热议问题