首页 > 技术文章 > Java 多线程编程之:notify 和 wait 用法

chong-zuo3322 2020-09-25 17:36 原文

wait和notify简介

wait和notify都输属于object的方法

object.wait():  暂停一个线程.

object.notify():  唤醒一个线程.

想要实现wait和notify方法首先需要一个object对象. 在多个线程之间,我们可以通过调用同一个对象的wait()和notify()来实现不同线程之间的可见.

 

对象控制权(monitor)

在使用wait和notify之前, 我们需要了解对象的控制权(monitor). 在java中任何一个时刻, 对象的控制权只能被一个线程拥有.

代码说明:

public class ThreadTest2 {
public static void main(String[] args) {
Object object = new Object();

new Thread(new Runnable() {
@Override
public void run() {
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}).start();
}
}

会报错,因为我们没有获取对象的控制权.

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.ultiwill.test.threads.ThreadTest2$1.run(ThreadTest2.java:15)
    at java.lang.Thread.run(Thread.java:748)

出错的代码在object.wait(), 这里我们需要了解一下事实:

1.无论执行对象的wait(), notify(), notifyAll()方法, 必须保证当前运行的线程获取该对象的控制权.

2.我们可以通过同步锁来获得对象的控制权, 例如: synchronized代码块.

代码改造:

public class ThreadTest2 {
    public static void main(String[] args) {
        Object object = new Object();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object){
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        
    }
}

这样就不会报错.

 

扩展题:

使用两个线程, 一个输出1,3,5,7...99 另一个输出2,4,6,8...100, 最后stdout中按顺序输出1,2,3,4...100
public class ThreadDemo {

    private static Object object = new Object();

    public static void main(String[] args) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object) {
                    for (int i = 0; i <= 100; i += 2) {
                        //唤醒线程
                        object.notify();

                        System.out.println(i);
                        try {
                            //暂停线程
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (object) {
                    for (int i = 1; i <= 100; i += 2) {
                        //唤醒线程
                        object.notify();

                        System.out.println(i);
                        try {
                            //暂停线程
                            object.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }).start();

    }


}

 

推荐阅读