java的wait()方法使用注意事项

来源:互联网 发布:淘宝评价过了怎么截图 编辑:程序博客网 时间:2024/05/18 01:50

1.本文解决的问题

(1)wait()方法一定要使用sycronized进行同步吗?不用sycronized修饰会有什么问题?
(2)wait()方法会释放对象锁,那么这里指的锁是什么?
(3)wait()会释放对象锁,而sleep()不会释放对象锁,这在实际情况中有什么区别?

2.结论

(1)wait()一定要使用sycronized进行同步,否则会报“java.lang.IllegalMonitorStateException”异常。这是因为wait方法会释放对象锁,而此时因为没有用sycronized同步,就没有锁,就会报异常。
(2)锁指的是sycronized修饰的方法、对象、代码块,如下实例中的value。
(3)因为wait()释放了锁,故其他线程可以执行本来由sycronized修饰的内容。例如下面实例中的run()方法内打印value值(System.out.println(value);)。

3.实例

如下,我们首先新建自己的线程类,覆写run()方法,新线程的作用是判断传进来的值是不是”123”,如果是就等待10s,不是就修改传进来的值并打印出来。

public class MyThread extends Thread {    StringBuilder value;    public MyThread(StringBuilder value) {        this.value = value;    }    @Override    public void run() {        try {            synchronized(value) {                 System.out.println(value);                if ((value.toString()).equals("123")) {                    System.out.println(getName() + "开始等待;当前时间秒数:" + Calendar.getInstance().get(Calendar.SECOND));                    value.wait(10000);// 注意这里不是说让value进行wait,而是让当前线程进行wait                } else {                    value = value.append("2");                    System.out.println("当前线程名:" + getName() + ";" + value );                }            }        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}

然后在主函数中新建三个自己定义的线程并运行:

    public static void main(String[] args) {        // TODO Auto-generated method stub        StringBuilder value = new StringBuilder("123");        MyThread myThread1 = new MyThread(value);        MyThread myThread2 = new MyThread(value);        MyThread myThread3 = new MyThread(value);        myThread1.start();        myThread2.start();        myThread3.start();    }

这个程序的执行结果为:

123Thread-0开始等待;当前时间秒数:5123Thread-2开始等待;当前时间秒数:5123Thread-1开始等待;当前时间秒数:5

如果我们把MyThread类的第9行和第18行,也就是sycronized的修饰去掉,就会报“java.lang.IllegalMonitorStateException”异常。
如果我们把MyThread类的第13行的value.wait(10000)语句替换为sleep(10000),则输出如下:

123Thread-1开始等待;当前时间秒数:5123Thread-0开始等待;当前时间秒数:15123Thread-2开始等待;当前时间秒数:25

由输出的时间秒数可见,使用sleep会使三个线程依此执行,一个等待完10s后另一个才会进入sycronized内进行等待。而使用wait,则三个线程基本都是一起开始等待的,也就是wait会释放对value的锁定,其他线程可以执行sycronized代码块中的语句。另外使用sleep并不一定非要同步,这里是为了验证sleep不会释放锁。

原创粉丝点击