线程等待、通知、通知全部
java 中的Object类包含三个final 方法
- wait()
- notify()
- notifyAll()
简介
在任何对象上调用这些方法的当前线程应该具有对象监视器,否则会抛出
java.lang.IllegalMonitorStateException
等待
wait()
对象等待方法由三个
- 一个是等待无限期,等待其他任何线程调用对象上的notify或notifyAll方法来唤醒当前线程;
- 另外两个是是当前线程在唤醒前等待特定的时间间隔
通知
notify 方法只唤醒一个等待该对象的线程,该线程开始执行。
如果有多个线程在等待对象,则此方法将仅唤醒其中的一个,要唤醒的线程取决于线程管理的OS
通知全部
notifyAll 唤醒等待对象的所有线程,但首先唤醒哪个线程仍由OS决定
这些方法会产生生产者消费者问题,消费者线程正在等待队列中的对象,生产者线程将对象放入队列并通知等待的线程
举例
package coreofjava.javathread.threadwaitnotifyandnotifyall;
public class Message {
private String msg;
public Message(String str) {
this.msg = str;
}
public String getMsg() {
return msg;
}
public void setMsg(String str) {
this.msg = str;
}
}
线程将在其上工作的java bean类,并调用 wait 和 notify 方法
package coreofjava.javathread.threadwaitnotifyandnotifyall;
public class Waiter implements Runnable{
private Message msg;
public Waiter(Message m) {
this.msg = m;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
synchronized (msg) {
try {
System.out.println(name + " 等待通知, 时间 : " + System.currentTimeMillis());
msg.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name + " 等待线程获得通知 , 时间 : " + System.currentTimeMillis());
// 处理消息
System.out.println(name + " 已处理 : " + msg.getMsg());
}
}
}
将等待其他线程调用 notify 类来完成处理的类, Waiter 线程使用 synchronized 块在 Message 对象上拥有监视器
package coreofjava.javathread.threadwaitnotifyandnotifyall;
public class Notifier implements Runnable {
private Message msg;
public Notifier(Message msg) {
this.msg = msg;
}
/**
* 如果只调用 notify() 则线程中的一个被调用,另一个被挂起,则程序不会结束
* 如果使用 notifyAll(), 则所有线程将会被运行
*/
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name + " 开始");
try {
Thread.sleep(1000);
synchronized (msg) {
msg.setMsg(name + " 通知工作完成");
msg.notify();
// msg.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
将在 Message 对象上处理然后调用 notify方法来唤醒等待 Message对象的线程的类。 synchronized 块用于拥有 Message对象的监视器
package coreofjava.javathread.threadwaitnotifyandnotifyall;
public class WaitNotifyTest {
public static void main(String[] args) {
Message msg = new Message(" 开始处理");
Waiter waiter = new Waiter(msg);
new Thread(waiter, "waiter").start();
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1, "waiter1").start();
Notifier notifier = new Notifier(msg);
new Thread(notifier, "notifier").start();
System.out.println("所有线程开始");
}
}
测试类将创建Waiter和 Notifier 的多个线程并启动
当通知类使用 notify() 只有一个线程被调用, 若使用 notifyAll ,则所有线程将被调用