线程通信问题,及案例
线程的状态(六种)
新建状态 阻塞状态 运行状态 死亡状态 休眠状态 无限等待状态
简单来说就是 wait() 和 notify() 一个让进程等待,一个唤醒进程.
案例: 一个包子铺 一个做包子的老板线程;一个吃包子的顾客线程;
/*
等待唤醒案例:线程之间的通信
创建一个顾客线程(消费者):告知老板要包子的种类和数量,调用wait方法,放弃cpu的执行,进入到WAITING状态
创建老板线程(生产者):花了5秒做包子,做好包子,调用notify方法,唤醒顾客吃包子
注意:
顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行
同步使用的锁对象必须保证唯一
只有锁对象才能调用wait和notify方法
*/
public class Demo01WaitAndNotify {
public static void main(String[] args) {
Object obj=new Object();
//顾客吃包子
//匿名内部类创建线程
new Thread(){
@Override
public void run() {
while (true){
synchronized (obj){
System.out.println("顾客点包子吃");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("顾客吃点包子");
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
System.out.println("师傅用五秒钟做包子");
//唤醒进程
obj.notify();
}
}
}
}.start();
}
}
引用黑马程序员老师的案例图片
分析:需要哪些类
资源类:包子类
设置包子的属性
皮
陷
包子的状态:有(true)或无(false)
生产者(包子铺)类:是一个线程类.可以继承Thread
设置线程任务(重写run方法):生产包子
if(包子true?):
调用wait方法进入等待状态
false:没有包子
包子铺生产包子
增加趣味性:交替生产两种包子
有两种状态(i%2==0)
包子铺生产好了包子
修改包子状态为true
唤醒吃货线程,让吃货线程吃包子
吃货线程:继承Thread类
重写run方法
对包子状态进行判断
false:wait;
true:吃包子;吃完包子修改包子状态为false没有,唤醒包子铺线程
测试类:
包含Main方法,
创建包子对象;创建包子铺线程.start(),开启:吃货线程.start()
/*
等待唤醒案例:线程之间的通信
创建一个顾客线程(消费者):告知老板要包子的种类和数量,调用wait方法,放弃cpu的执行,进入到WAITING状态
创建老板线程(生产者):花了5秒做包子,做好包子,调用notify方法,唤醒顾客吃包子
注意:
顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行
同步使用的锁对象必须保证唯一
只有锁对象才能调用wait和notify方法
*/
public class Demo01WaitAndNotify {
public static void main(String[] args) {
Object obj=new Object();
//顾客吃包子
//匿名内部类创建线程
new Thread(){
@Override
public void run() {
while (true){
synchronized (obj){
System.out.println("顾客点包子吃");
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("顾客吃点包子");
}
}
}
}.start();
new Thread(){
@Override
public void run() {
while (true){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj){
System.out.println("师傅用五秒钟做包子");
//唤醒进程
obj.notify();
}
}
}
}.start();
}
}
包子:
package demo01.demo20.BaoZIAnli;
public class BaoZi {
String pi;
String xian;
public String getPi() {
return pi;
}
public void setPi(String pi) {
this.pi = pi;
}
public String getXian() {
return xian;
}
public void setXian(String xian) {
this.xian = xian;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public BaoZi() {
}
public BaoZi(String pi, String xian, boolean flag) {
this.pi = pi;
this.xian = xian;
this.flag = flag;
}
boolean flag;
}
吃货:
package demo01.demo20.BaoZIAnli;
import static demo01.demo20.BaoZIAnli.BaoZiPu.count;
public class ChiHuo extends Thread {
private BaoZi bz;
public ChiHuo(BaoZi bz){
this.bz=bz;
}
@Override
public void run() {
while (true){
synchronized (bz){
if (bz.flag==false){
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//被唤醒后执行的代码
System.out.println("吃货正在吃:"+bz.pi+bz.xian+"包子");
bz.flag=false;
bz.notify();
System.out.println("包子吃完了,老板生产包子啦");
System.out.println("吃货已经吃了"+count);
System.out.println("========================");
}
}
}
}
包子铺
package demo01.demo20.BaoZIAnli;
public class BaoZiPu extends Thread {
public static int count=0;
private BaoZi bz;
public BaoZiPu(BaoZi bz){
this.bz=bz;
}
@Override
public void run() {
while (true){
synchronized (bz){
if (bz.flag==true){
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//被唤醒后执行,包子铺生产包子
//增加一些趣味性:交替生产两种包子
if (count%2==0){
bz.pi="薄皮";
bz.xian="三鲜馅";
}else {
bz.pi="冰皮";
bz.xian="猪肉大葱";
}
count++;
System.out.println("正在生产"+bz.pi+bz.xian+"包子");
//生产包子需要3秒钟
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bz.flag=true;
bz.notify();
System.out.println("包子铺已经生产好了"+bz.pi+bz.xian+"包子"+"吃货可以吃了");
System.out.println("包子已经生产了"+count);
System.out.println("========================");
}
}
}
}
测试类
package demo01.demo20.BaoZIAnli;
public class Test {
public static void main(String[] args) {
BaoZi bz=new BaoZi();
new BaoZiPu(bz).start();
new ChiHuo(bz).start();
}
}