Object有关于多线程的默认方法,它们的作用如下:
wait() : 使得调用的此方法的线程等待
notify() : 唤醒一个等待中的线程(通常是最先等待的线程)
notifyAll():唤醒所有等待中的线程(倒序唤醒,即最近wait()最先被唤醒)
使用前提
上面三个方法,使用之前必须获得锁,即必须在synchronized方法里面或者
synchronized代码块中使用,如:
public class A {
synchronized public void backupA() {
try {
System.out.println("A wait");
wait();
System.out.println("A run");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
我们可以看到 wait()其实可以写成this.wait(),说明是该类的实例对象调用此方法,
而synchronized方法使用的锁对象也是this,即该类的实例对象
说明wait()不止得在同步方法或同步块中使用,还必须是锁对象来调用此方法,
notify()和notifyAll()也一样
我们可以把代码改成
public class A {
private Object object = new Object();
synchronized public void backupA() {
try {
System.out.println("A wait");
object.wait();
System.out.println("A run");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
可以看出调用wait()的对象,不是锁对象,在重写的run()方法中调用此方法
会出现java.lang.IllegalMonitorStateException异常,就是因为使用wait()方法的对象
并没有获得监视器,即没有获得锁
唤醒线程是唤醒哪些线程呢,任意等待线程吗
结论:锁对象调用notify()和notifyAll()方法只能唤醒该锁对象调用wait()的线程,简单来说就是如果有两个锁对象,一个锁对象运行wait()使得该线程等待,另外一个锁对象运行
唤醒方法notify()将无法唤醒
例子如下,有5个类
A.class
B.class
ThreadA.class
ThreadB.class
Test.class
A.class
public class A {
synchronized public void backupA() {
try {
System.out.println("A wait");
this.wait();
System.out.println("A run");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
B.class
public class B {
synchronized public void backupB() {
System.out.println("B notify");
this.notify();
System.out.println("B run");
}
}
ThreadA.class
public class ThreadA extends Thread {
private A a;
public ThreadA(A a) {
this.a = a;
}
@Override
public void run() {
a.backupA();
}
}
ThreadB.class
public class ThreadB extends Thread {
private B b;
public ThreadB(B b) {
this.b = b;
}
@Override
public void run() {
b.backupB();
}
}
Test.class
public class Test {
public static void main(String[] args) throws InterruptedException {
A a = new A();
B b = new B();
ThreadA threadA = new ThreadA(a);
ThreadB threadB = new ThreadB(b);
threadA.start();
Thread.sleep(500);
threadB.start();
}
}
结果
可以看出B类中运行的notify() 无法唤醒A类中运行wait()方法后等待的线程,
因为B类中使用B的实例对象作为锁,A类中使用A的实例对象作为锁,两者锁不同,
则使用wait()和notify()的对象不同,无法唤醒