线程等待唤醒机制。
用到的API, 下面的方法都是Object中的。
void wait(): 让当前的线程等待。
void notify(): 随机唤醒一个线程
void notifyAll(): 唤醒所有的线程。
上面这些方法虽然是Object中的方法,但是不能通过对象直接去调用
这些方法一定要放在同步代码块中,并且使用锁对象(对象监视器)去调用。
当一个线程调用wait方法后,会释放自己的锁。
wait和sleep的方法的区别了:
wait方法会释放锁
sleep方法不会释放锁。
案例:
包子铺 吃货。 包子铺做包子,做完包子通知(notify)吃货吃包子。包子铺等待吃货吃完,然后通知(notif)包子铺做包子。当两个线程共享同一种数据时,容易出现线程安全问题。
1.定义包子类。该类作为锁对象。
public class BaoZi {
//定义成员变量,表示包子是否存在
public boolean flag=false;
public String xianer;
}
2.定义包子铺和。吃货类:‘传参:创建的包子类作为参数,传到包子铺和吃货类。用变量接收,这样可以保证,包子铺和吃货吃的是同一个包子
public class BaoZiPu implements Runnable {
private BaoZi baoZi;//定义一个成员变量,
public BaoZiPu(BaoZi baoZi) {//构造方法,当我创建包子铺的对象时候就可以从外界传入一个
// 包子对象,然后把包子对象赋值给成员变量,这样就可以保证,包子铺里面的包子和吃货里面的包
// 子是同一个包子
this.baoZi = baoZi;
}
//包子铺线程执行的任务
@Override
public void run() {
while (true) {
//因为包子铺和吃货所用的包子是同一个,所以可以把包子当成锁对象
synchronized (baoZi) {//如果还有包子,则包子铺不做包子,等待吃货吃完
if (baoZi.flag) {
//调用wait方法,让包子铺这个线程等待
try {
baoZi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有包子,就生产包子,
System.out.println("包子铺生产了一个包子。快来吃");
baoZi.flag = true;//表示包子已经生成完成了
//包子铺生产完包子,提醒吃货去吃包子
baoZi.notify();
}
}
}
}
public class ChiHuo implements Runnable {
private BaoZi baoZi;
public ChiHuo(BaoZi baoZi) {
this.baoZi = baoZi;
}
//吃货线程要做的任务,吃包子
@Override
public void run() {
while (true) {
synchronized (baoZi) {
if (!baoZi.flag) {
//如果没有包子。则调用wait方法等待
try {
baoZi.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有包子,那就吃
baoZi.xianer="大饼";
System.out.println("吃货把这个包子吃完了,吃的是" +baoZi.xianer + "的包子");
baoZi.flag = false;
//如果吃完就通知包子铺线程去做包子
baoZi.notify();
}
}
}
}
3 测试类
package cn.itcast.demo01_thread;
/*
线程等待唤醒机制。
用到的API, 下面的方法都是Object中的。
void wait(): 让当前的线程等待。
void notify(): 随机唤醒一个线程
void notifyAll(): 唤醒所有的线程。
上面这些方法虽然是Object中的方法,但是不能通过对象直接去调用
这些方法一定要放在同步代码块中,并且使用锁对象(对象监视器)去调用。
当一个线程调用wait方法后,会释放自己的锁。
wait和sleep的方法的区别了:
wait方法会释放锁
sleep方法不会释放锁。
*/
public class Demo01Test {
public static void main(String[] args) {
//新建一个包子对象
BaoZi baozi = new BaoZi();
//新建一个包子铺对象
BaoZiPu baoZiPu = new BaoZiPu(baozi);
//新建一个吃货对象
ChiHuo chiHuo = new ChiHuo(baozi);
//分别创建两个线程去执行这两个任务
new Thread(baoZiPu).start();
new Thread(chiHuo).start();
}
}