`

wait,notify和notifyall应该注意的问题

阅读更多
在使用wait,notify和notifyall可能会抛出java.lang.IllegalMonitorStateException
首先我们先看看java.lang.IllegalMonitorStateException的说明:
public class IllegalMonitorStateExceptionextends RuntimeException

抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 

从以下版本开始: 
JDK1.0 


然后再贴2段代码,首先是一个会抛出该异常的代码
package com.wikimore.threadtest;


/**
 * Hello world!
 * 
 */
public class App {

    private static Object lock = new Object();

    public static void main(String[] args) {
        Runnable r1 = new Runnable() {

            public void run() {
                System.out.println("t1 running");
                    try {
                        System.out.println("t1 waiting");
                        lock.wait();
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t1 running again");
                    lock.notifyAll();
            }
        };
        Thread t1 = new Thread(r1, "thread-1");
        Runnable r2 = new Runnable() {

            public void run() {
                System.out.println("t2 running");
                    try {
                        System.out.println("t2 waiting");
                        lock.wait();
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t2 running again");
                    lock.notifyAll();
            }
        };
        Thread t2 = new Thread(r2, "thread-2");

        Runnable r3 = new Runnable() {

            public void run() {
                System.out.println("t3 running");
                    try {
                        System.out.println("t3 waiting");
                        lock.wait(1000);
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t3 running again");
                    lock.notifyAll();
            }
        };
        Thread t3 = new Thread(r3, "thread-3");
        t1.start();
        t2.start();
        t3.start();
    }
}

这段代码的线程在调用wait和notifyall方法时,均没有获得lock的同步锁,等于是没有指定监视器。

再来一段不会抛出异常的代码:
package com.wikimore.threadtest;

/**
 * Hello world!
 * 
 */
public class App {

    private static Object lock = new Object();

    public static void main(String[] args) {
        Runnable r1 = new Runnable() {

            public void run() {
                System.out.println("t1 running");
                synchronized (lock) {
                    try {
                        System.out.println("t1 waiting");
                        lock.wait();
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t1 running again");
                    lock.notifyAll();
                }
            }
        };
        Thread t1 = new Thread(r1, "thread-1");
        Runnable r2 = new Runnable() {

            public void run() {
                System.out.println("t2 running");
                synchronized (lock) {
                    try {
                        System.out.println("t2 waiting");
                        lock.wait();
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t2 running again");
                    lock.notifyAll();
                }
            }
        };
        Thread t2 = new Thread(r2, "thread-2");

        Runnable r3 = new Runnable() {

            public void run() {
                System.out.println("t3 running");
                synchronized (lock) {
                    try {
                        System.out.println("t3 waiting");
                        lock.wait(10000);
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t3 running again");
                    lock.notifyAll();
                }
            }
        };
        Thread t3 = new Thread(r3, "thread-3");
        t1.start();
        t2.start();
        t3.start();
    }
}


这段代码在运行wait方法前会获得lock的同步,故不会出现上述异常。

wait方法执行时会释放锁,所以如果不在同步块中执行的话,很可能就会出现异常。

与wait相似的sleep方法在执行时就不会释放锁,这个需要注意防止阻塞!
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics