1、wait()、notify/notifyAll() 方法是Object类的本地final方法,无法被重写。
2、wait()方法:
(1)作用:wait()使当前执行代码的线程进行等待,即使当前线程进入阻塞队列。
(2)使用条件:前提是 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 修饰同步代码块或同步方法里使用 wait()、notify/notifyAll() 方法。
(3)观察wait()方法使用:
public class testThread{
public static void main(String[] args) throws InterruptedException {
Object object = new Object();
synchronized (object) {
System.out.println("等待中...");
object.wait();
System.out.println("等待已过...");
}
System.out.println("main方法结束...");
}
}
执行结果:一直处于等待中
此时,就需要使用到notify()方法来唤醒。
3.notify()方法:
(1)作用:用来通知那些可能等待该对象的对象锁的其它线程,
对其发出通知notify,并使它们重新获取该对象的对象锁。如果有多个线程等待,则有线程规划器随机挑选出一个呈wait状态的线程。
(2)使用条件:也要在sychronized修饰的同步方法或同步代码块中调用。
(3)notify/notifyAll() 的执行只是唤醒沉睡的线程,而不会立即释放锁,锁的释放要看代码块的具体执行情况。所以在编程中,尽量在使用了notify/notifyAll() 后立即退出临界区,以唤醒其他线程 。
(4)观察notify()方法的使用:
class MyThread implements Runnable {
private boolean flag;
private Object obj;
public MyThread(boolean flag, Object obj) {
super();
this.flag = flag;
this.obj = obj;
}
public void waitMethod() {
synchronized (obj) {
try {
while (true) {
System.out.println("wait()方法开始.. " +
Thread.currentThread().getName());
obj.wait();
System.out.println("wait()方法结束.. " +
Thread.currentThread().getName());
return;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void notifyMethod() {
synchronized (obj) {
try {
System.out.println("notify()方法开始.. " +
Thread.currentThread().getName());
obj.notify();
System.out.println("notify()方法结束.. " +
Thread.currentThread().getName());
} catch (Exception e) {e.printStackTrace();
}
}
}
@Override
public void run() {
if (flag) {
this.waitMethod();
} else {
this.notifyMethod();
}
}
}
public class testThread{
public static void main(String[] args) throws InterruptedException {
Object object = new Object();
MyThread waitThread = new MyThread(true, object);
MyThread notifyThread = new MyThread(false, object);
Thread thread1 = new Thread(waitThread, "wait线程");
Thread thread2 = new Thread(notifyThread, "notify线程");
thread1.start();
Thread.sleep(1000);
thread2.start();
System.out.println("main方法结束!!");
}
从结果上来看第一个线程执行的是一个waitMethod方法,该方法里面有个死循环并且使用了wait方法进入等待状态将释放锁,如果这个线程不被唤醒的话将会一直等待下去,这个时候第二个线程执行的是notifyMethod方法,该方法里面执行了一个唤醒线程的操作,并且一直将notify的同步代码块执行完毕之后才会释放锁然后继续执行wait结束打印语句。
5.notifyAll()方法:
(1)作用:唤醒所有等待中的线程。
(2)使用条件:与notify()方法一样。
(3)观察notifyAll()方法的使用:
class MyThread implements Runnable {
private boolean flag;
private Object obj;
public MyThread(boolean flag, Object obj) {
super();
this.flag = flag;
this.obj = obj;
}public void waitMethod() {
synchronized (obj) {
try {
while (true) {
System.out.println("wait()方法开始.. " +
Thread.currentThread().getName());
obj.wait();
System.out.println("wait()方法结束.. " +
Thread.currentThread().getName());
return;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void notifyMethod() {
synchronized (obj) {
try {
System.out.println("notifyAll()方法开始.. " +
Thread.currentThread().getName());
obj.notifyAll();
System.out.println("notifyAll()方法结束.. " +
Thread.currentThread().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}@Override
public void run() {
if (flag) {
this.waitMethod();
} else {
this.notifyMethod();
}
}
}
public class testThread {
public static void main(String[] args) throws InterruptedException {
Object object = new Object();
MyThread waitThread1 = new MyThread(true, object);
MyThread waitThread2 = new MyThread(true, object);
MyThread waitThread3 = new MyThread(true, object);
MyThread notifyThread = new MyThread(false, object);
Thread thread1 = new Thread(waitThread1, "wait线程A");
Thread thread2 = new Thread(waitThread2, "wait线程B");
Thread thread3 = new Thread(waitThread3, "wait线程C");
Thread thread4 = new Thread(notifyThread, "notify线程");
thread1.start();
thread2.start();
thread3.start();
Thread.sleep(1000);
thread4.start();
System.out.println("main方法结束!!");
}
6.注意事项:
(1)wait() 需要被try catch包围,中断也可以使wait等待的线程唤醒。
(2)notify 和wait 的顺序不能错,如果A线程先执行notify方法,B线程在执行wait方法,那么B线程是无法被唤醒的。
7、notify 和 notifyAll的区别
notify方法只唤醒一个等待(对象的)线程并使该线程开始执行。所以如果有多个线程等待一个对象,这个方法只会唤醒其中一个线程,选择哪个线程取决于操作系统对多线程管理的实现。notifyAll 会唤醒所有等待(对象的)线程,尽管哪一个线程将会第一个处理取决于操作系统的实现。如果当前情况下有多个线程需要被唤醒,推荐使用notifyAll 方法。比如在生产者-消费者里面的使用,每次都需要唤醒所有的消费者或是生产者,以判断程序是否可以继续往下执行。
8.wait()方法与sleep()方法的区别:
(1)sleep()方法是Thread类中的方法,到一了定时间后该线程自动唤醒,不会释放对象锁。
(2)wait()是Object类中定义的方法,要想唤醒必须使用nofify()/notifyAll()方法唤醒,会释放对象锁。