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(); } }