多线程(生产者和消费者问题)
锁对象类
//存在库存的饺子类
public class JiaoZi {
String pier;
String xianer;
//事先定义一个库存
int count = 0; //库存(有0份饺子)
}
生产者类(线程)
//饺子铺【生产者】
public class JiaoZiPu implements Runnable {
private JiaoZi jz;
public JiaoZiPu(JiaoZi jz) {
this.jz = jz;
}
//让王师傅我帮你
@Override
public void run() {
while (true) {
synchronized (jz) {
if (jz.count >= 20) { //生产当库存超过20,停下来
try {
jz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//休眠
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//变化
jz.count++;
jz.pier = "牛皮";
jz.xianer = "羊肉";
System.out.println("饺子铺:" + jz.pier + "," + jz.xianer + ",库存个数:" + jz.count);
//唤醒
jz.notify();
}
}
}
}
消费者类(线程)
//吃货【消费者】
public class ChiHuo implements Runnable {
private JiaoZi jz;
public ChiHuo(JiaoZi jz) {
this.jz = jz;
}
//让王师傅我帮你
@Override
public void run() {
while(true){
synchronized (jz){
if (jz.count<= 0) { //库存没有的时候,吃货要等待
try {
jz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//休眠
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//变化
jz.count--;
System.out.println("吃货:"+jz.pier+","+jz.xianer+",剩余个数:"+jz.count);
//唤醒
jz.notify();
}
}
}
}
测试类(开启线程)
//测试类.开启线程
public class Demo {
public static void main(String[] args) {
//创建饺子
JiaoZi jz = new JiaoZi();
//创建线程
Thread scz = new Thread(new JiaoZiPu(jz));
Thread xfz = new Thread(new ChiHuo(jz));
//开启线程
scz.start();
xfz.start();
}
}生产者与消费者问题
等待唤醒机制其实就是经典的“生产者与消费者”的问题。
就拿生产包子消费包子来说等待唤醒机制如何有效利用资源:
包子铺线程生产包子,吃货线程消费包子。当包子没有时(包子状态为false),吃货线程等待,包子铺线程生产包子(即包子状态为true)
并通知吃货线程(解除吃货的等待状态),因为已经有包子了,那么包子铺线程进入等待状态。
接下来,吃货线程能否进一步执行则取决于锁的获取情况。如果吃货获取到锁,那么就执行吃包子动作,包子吃完(包子状态为false)
并通知包子铺线程(解除包子铺的等待状态),吃货线程进入等待。包子铺线程能否进一步执行则取决于锁的获取情况。
代码演示:
包子资源类:
public class BaoZi {
String pier ;
String xianer ;
boolean flag = false ;//包子资源 是否存在 包子资源状态
}
吃货线程类:
public class ChiHuo extends Thread{
private BaoZi bz;
public ChiHuo(String name,BaoZi bz){
super(name);
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.pier+bz.xianer+"包子");
bz.flag = false;
bz.notify();
}
}
}
}
包子铺线程类:
public class BaoZiPu extends Thread {
private BaoZi bz;
public BaoZiPu(String name,BaoZi bz){
super(name);
this.bz = bz;
}
@Override
public void run() {
int count = 0;
//造包子
while(true){
//同步
synchronized (bz){
if(bz.flag == true){//包子资源 存在
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 没有包子 造包子
System.out.println("包子铺开始做包子");
if(count%2 == 0){
// 冰皮 五仁
bz.pier = "冰皮";
bz.xianer = "五仁";
}else{
// 薄皮 牛肉大葱
bz.pier = "薄皮";
bz.xianer = "牛肉大葱";
}
count++;
bz.flag=true;
System.out.println("包子造好了:"+bz.pier+bz.xianer);
System.out.println("吃货来吃吧");
//唤醒等待线程 (吃货)
bz.notify();
}
}
}
}
测试类:
public class Demo {
public static void main(String[] args) {
//等待唤醒案例
BaoZi bz = new BaoZi();
ChiHuo ch = new ChiHuo("吃货",bz);
BaoZiPu bzp = new BaoZiPu("包子铺",bz);
ch.start();
bzp.start();
}
}