天天看點

多線程的IllegalMonitorStateException異常分析

今天看了一篇線程通信的文章。想着研究一下線程之間的通信,使用的是object方法的wait和notify進行實作。代碼如下:

public static void demo2() {
        final Thread A = new Thread(new Runnable() {
            @Override
            public void run() {
                    System.out.println("A1");
                    try {
                        //調用wait,notify,notifyAll時,必須要擁有該對象的鎖
                        //如果沒有擁有該對象的鎖卻調用該對象的wait,notify,notifyAll方法
                        //就會報出IllegalMonitorStateException異常
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("A2");
                    System.out.println("A3");
                }
        });
        Thread B = new Thread(new Runnable() {
            @Override
            public void run() {
                    System.out.println("B1");
                    System.out.println("B2");
                    System.out.println("B3");
                    lock.notify();
                }
        });
        A.start();
        B.start();
    }
           

編譯不報錯,但是運作程式時報錯,報錯如下:

Exception in thread "Thread-0" A1
B1
B2
B3
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at cn.org.bjca.ThreadCommunicate$3.run(ThreadCommunicate.java:57)
	at java.lang.Thread.run(Thread.java:745)
java.lang.IllegalMonitorStateException
	at java.lang.Object.notify(Native Method)
	at cn.org.bjca.ThreadCommunicate$4.run(ThreadCommunicate.java:71)
	at java.lang.Thread.run(Thread.java:745)

Process finished with exit code 0
           

在網上搜尋了一下,知道了原因,特在此記錄一下。

調用wait,notify,notifyAll時,必須要擁有該對象的鎖,

如果沒有擁有該對象的鎖卻調用該對象的wait,notify,notifyAll方法

就會報出IllegalMonitorStateException異常

擷取一個對象鎖的最簡單方式是使用synchronized關鍵字。

代碼修改如下:

public static void demo2() {
        final Object lock = new Object();
        final Thread A = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock){
                    System.out.println("A1");
                    try {
                        //調用wait,notify,notifyAll時,必須要擁有該對象的鎖
                        //如果沒有擁有該對象的鎖卻調用該對象的wait,notify,notifyAll方法
                        //就會報出IllegalMonitorStateException異常
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("A2");
                    System.out.println("A3");
                }
            }
        });
        Thread B = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock){
                    System.out.println("B1");
                    System.out.println("B2");
                    System.out.println("B3");
                    lock.notify();
                }
            }
        });
        A.start();
        B.start();
    }
           

OK,問題解決,程式可以正常執行。

繼續閱讀