为了支持多线程之间的协作,jdk提供了两个非常重要的方法线程等待wait()和通知notify()方法,这两个方法不是Thread类的,而是属于Object类。
方法的方法签名:
当一个对象实例调用了wait()方法之后,当前线程就会在这个对象上等待。比如线程A中调用了obj.wait()方法,线程A就会停止继续执行而转为等待状态,等待状态持续到其他线程调用了obj.notify()或obj.notifyAll()为止。
当一个线程调用了obj.wait(),这个线程就会进入obj这个对象的等待队列中。obj.notify()会在这个对象的等待队列中随机选择一个线程进行通知唤醒;而notifyAll()则是通知唤醒等待线程队列中所有的线程。
还有就是wait和notify都必须包含在对应的synchronized语句中,无论是wait()还是notify()都需要先获取目标对象的一个监视器,并且执行之后都会释放这个监视器,如下图所示
wait()和notify()的例子:生产者消费者问题,代码如下
package com.bckj.Thread;
/**
* Created by Admin on 2017/6/12.
*/
//仓库类
public class Store {
private final int MAX_SIZE; //仓库的最大容量
private int count; //当前的仓库数量
public Store(int n){
MAX_SIZE = n;
count = 0;
}
//往仓库加货物的方法
public synchronized void add(){ //使用了wait()或notify()方法,需要加上syncronized关键字
while(count >= MAX_SIZE){ //否则可能会抛出java.lang.IllegalMonitorStateException
System.out.println("已经满了");
try{
this.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
count++;
//打印当前仓库的货物数量
System.out.println(Thread.currentThread().toString()+" put"+count);
//仓库中已经有东西可以取了,则通知所有的消费者线程来拿
this.notifyAll();
}
//从仓库拿走货物的方法
public synchronized void remove(){
while(count <= 0){
System.out.println("空了");
try{
this.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
}
//打印当前仓库的货物数量
System.out.println(Thread.currentThread().toString()+" get"+count);
count--;
//仓库还没装满,通知生产者添加货物
this.notify();
}
public static void main(String[] args) {
Store s = new Store(5); //创建容量为5的仓库
//创建两个生产者和两个消费者
Thread pro = new Producer(s);
Thread con = new Consumer(s);
Thread pro2 = new Producer(s);
Thread con2 = new Consumer(s);
pro.setName("producer");
con.setName("consumer");
pro2.setName("producer2");
con2.setName("consumer2");
//启动各个线程
pro.start();
pro2.start();
con.start();
con2.start();
}
}
class Producer extends Thread{ //生产者线程类
private Store s;
public Producer(Store s){
this.s = s;
}
public void run(){ //线程方法
while(true){ //永久循环
s.add(); //往仓库加货物
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
class Consumer extends Thread{ //消费者线程类
private Store s;
public Consumer(Store s){
this.s = s;
}
public void run(){ //线程方法
while(true){ //永久循环
s.remove(); //往仓库取走货物
try{
Thread.sleep(1500);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
}
执行结果: