* wait()、notify()和notifyAll()方法是本地方法,并且为final方法,无法被重写。
* 调用某个对象的wait()。让出对象所有权,休眠当前线程
* 调用某个对象的notify()方法能够唤醒一个正在等待这个对象的monitor的线程
* 如果有多个线程都在等待这个对象的monitor,则只能唤醒其中一个线程。
* 唤醒后并还不能执行,还必须等到获取对象所有权才能执行。
* 调用notifyAll()方法能够唤醒所有正在等待这个对象的monitor的线程。
* 唤醒后并还不能执行,还必须等到获取对象所有权才能执行。
* 要同步的代码块必须要使用synchronized包含起来,代码块执行完毕后才会释放对象所有权
// 上面尤其要注意一点,一个线程被唤醒不代表立即获取了对象的monitor(锁),
// 只有等调用完notify()或者notifyAll()并退出synchronized块,释放对象锁后,
// 其余线程才能获得锁,才可获得锁执行。
public class Test {
public static Object object = new Object();
public static void main(String[] args) {
Thread1 thread1 = new Thread1(object);
Thread2 thread2 = new Thread2(object);
Thread3 thread3 = new Thread3(object);
thread2.start();
thread3.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {}
thread1.start();
}
}
class Thread1 extends Thread{
private Object object;
public Thread1(Object object){this.object = object;}
@Override
public void run() {
synchronized (object) { // 获取对象锁,该代码块才有执行的机会,其他线程则无法执行被该对象锁住的代码块
// object.notify(); // Thread2,Thread3只有一个线程被唤醒,并获得锁(object对象),执行代码块,释放锁,另外一个线程永远没有机会被唤醒
object.notifyAll(); // Thread2,Thread3两个线程都被唤醒,但是每个时刻只有一个线程获得锁(object对象),执行完毕之后,
// 另一个线程获得锁,执行代码块,释放锁
System.out.println("线程"+Thread.currentThread().getName()+"调用了object.notify()");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} // synchronized语句块执行完毕才释放锁
System.out.println("线程" + Thread.currentThread().getName() + "释放了锁");
}
}
class Thread2 extends Thread{
private Object object;
public Thread2(Object object){this.object = object;}
@Override
public void run() {
synchronized (object) {
try {
System.out.println("线程" + Thread.currentThread().getName() + "sleep");
object.wait();
// object.notify();
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁");
}
}
}
class Thread3 extends Thread{
private Object object;
public Thread3(Object object){this.object = object;}
@Override
public void run() {
synchronized (object) {
try {
System.out.println("线程" + Thread.currentThread().getName() + "sleep");
object.wait();
// object.notify();
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println("线程"+Thread.currentThread().getName()+"获取到了锁");
}
}
}