簡體   English   中英

從同步塊中調用wait時發生java.lang.IllegalMonitorStateException

[英]java.lang.IllegalMonitorStateException whilst calling wait from synchronized block

在繼續使用Condition變量之前,我試圖了解對象等待原理。 我寫了一些代碼以了解更多信息,但是它沒有按預期工作。

應該發生的是Waiter類在線程啟動時等待。 同時,Notifier類使用循環將一些元素添加到列表中。 通知程序完成此操作后,它會通知服務員,該服務員應簡單地打印已收到通知,但我收到了非法的monitorstate異常

這是我的輸出

Exception in thread "Waiter Thread" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at tutorials.waitnotify.Waiter.run(Waiter.java:26)
at java.lang.Thread.run(Thread.java:745)
0 [Waiter Thread] DEBUG tutorials.waitnotify.Waiter  - Starting waiter....
2002 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter  - Starting     
notifier...
3005 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter  - Element added [1]
4007 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter  - Element added [2]
5012 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter  - Element added [3]
Exception in thread "Notifier Thread" java.lang.IllegalMonitorStateException
7022 [Notifier Thread] DEBUG tutorials.waitnotify.Waiter  - Object about to    
notify
at java.lang.Object.notify(Native Method)
at tutorials.waitnotify.Notifier.run(Notifier.java:42)
at java.lang.Thread.run(Thread.java:745)

這是代碼如您所見,我正在嘗試在通用鎖定對象上進行同步。

public class Notifier implements Runnable {

private static final Logger LOGGER = LoggerFactory.getLogger(Waiter.class);
private List<Integer> list;
private Object commonLock;

public Notifier(Object lock) {
    this.list = new ArrayList<>();
    this.commonLock = lock;
}

public void run() {
    LOGGER.debug("Starting notifier....");
    synchronized (commonLock) {
        for (int i = 1; i <= 3; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                LOGGER.debug("Interrupted");
            }
            list.add(i);
            LOGGER.debug("Element added [{}]", i);
        }
        LOGGER.debug("About to notify");
        notify();
    }
}
}

public class Waiter implements Runnable {

private static final Logger LOGGER = LoggerFactory.getLogger(Waiter.class);
private final Object commonLock;

public Waiter(Object lock) {
    this.commonLock = lock;
}

public void run() {
    LOGGER.debug("Starting waiter....");
    synchronized (commonLock) {
        try {
            wait(10000);
        } catch (InterruptedException ie) {
            LOGGER.debug("Interrupted");
        }
    }
    LOGGER.debug("Object been notified");
}
}

public class WaiterNotifierMain {

public static void main(String[] args) {
    BasicConfigurator.configure();

    Object lock = new Object();
    Waiter waiter = new Waiter(lock);
    Notifier notifier = new Notifier(lock);

    Thread waiterThread = new Thread(waiter);
    Thread notifierThread = new Thread(notifier);

    notifierThread.setName("Notifier Thread");
    waiterThread.setName("Waiter Thread");
    waiterThread.start();
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    notifierThread.start();
}
}

任何指針將不勝感激。 提前致謝

你應該做

  • commonLock .wait(10000)
  • commonLock .notify()

因為您正在等待並通知“此”,所以您會得到一個例外。 而且您沒有在“ this”上同步。

您可以考慮使用notifyAll()而不是notify():

如果您打算有多個Waiter線程,請記住,notify()一次只會喚醒一個Waiter線程。 如果要立即喚醒所有Waiter線程,則應改用notifyAll()方法。

即使知道您永遠不會有一個以上的Waiter線程,但我認為最好的方法是使用notifyAll()而不是notify(),因為Notifier對象不知道有多少線程正在該對象上偵聽...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM