问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

JAVA多生产者多消费者问题。希望用wait()和notify().谢谢!

发布网友 发布时间:2022-04-30 03:35

我来回答

2个回答

热心网友 时间:2023-10-09 20:32



public class ProceConsumerDemo {

public static void main(String[] args) {
// 1.创建资源
Resource resource = new Resource();
// 2.创建两个任务
Procer procer = new Procer(resource);
Consumer consumer = new Consumer(resource);
// 3.创建线程
/*
* 多生产多消费产生的问题:重复生产、重复消费
*/
Thread thread0 = new Thread(procer);
Thread thread1 = new Thread(procer);

thread0.setName("生产者(NO0)");
thread1.setName("生产者(NO1)");

Thread thread2 = new Thread(consumer);
Thread thread3 = new Thread(consumer);

thread2.setName("消费者(NO2)");
thread3.setName("消费者(NO3)");

thread0.start();
thread1.start();
thread2.start();
thread3.start();
}
}

class Resource {
private String name;
private int count = 1;
// 定义标记
private boolean flag;

// 提供给商品赋值的方法
public synchronized void setName(String name) {// thread0, thread1在这里运行
while (flag)// 判断标记为true,执行wait等待,为false则生产
/*
* 这里使用while,而不使用if的理由如下:

* thread0有可能第二次也抢到锁的执行权,判断为真,则有面包不生产,所以接下来执行等待,此时thread0在线程池中。
* 接下来活的线程有3个(除了thread0),这三个线程都有可能获取到执行权.
* 假设thread1获得了执行权,判断为真,则有面包不生产,执行等待。此时thread1又进入到了线程池中。
* 接下来有两个活的线程thread2和thread3。 假设thread2又抢到了执行权,所以程序转到了消费get处……
*/
try {
this.wait();//这里wait语句必须包含在try/catch块中,抛出异常。
} catch (InterruptedException e) {
e.printStackTrace();
}
this.name = name + count;// 第一个面包
count++;// 2
System.out.println(Thread.currentThread().getName() + this.name);// thread0线程生产了面包1

// 生产完毕,将标记改成true.
flag = true;// thread0第一次生产完面包以后,将标记改为真,表示有面包了

// 唤醒消费者(这里使用notifyAll而不使用notify的原因在下面)

this.notifyAll();// 第一次在这里是空唤醒,没有意义
}

/*
* 通过同步,解决了没生产就消费的问题
* 生产完以后,生产者释放了this锁,此时,生产者和消费者同时去抢锁,又是生产者抢到了锁,所以就出现了一直生产的情况。
* 与“生产一个就消费一个的需求不符合” 等待唤醒机制 wait();该方法可以使线程处于冻结状态,并将线程临时存储到线程池
* notify();唤醒指定线程池中的任意一个线程。 notifyAll();唤醒指定线程池中的所有线程
* 这些方法必须使用在同步函数中,因为他们用来操作同步锁上的线程上的状态的。
* 在使用这些方法时候,必须标识他们所属于的锁,标识方式就是锁对象.wait(); 锁对象.notify(); 锁对象.notifyAll();
* 相同锁的notify()可以获取相同锁的wait();
*/

public synchronized void getName() {// thread2,thread3在这里运行
while (!flag)
/*
* ……接着上面的程序执行分析 thread2拿到锁获取执行权之后,判断!flag为假,则不等待,直接消费面包1,输出一次.
* 消费完成之后将flag改为假 接下来又唤醒了thread0或者thread1生产者中的一个
* 假设又唤醒了thread0线程,现在活的线程有thread0,thread2,thread3三个线程
* 假设接下来thread2又抢到了执行权,判断!flag为真,没面包了,停止消费,所以thread2执行等待.
* 此时活着的线程有thread0和thread3。
* 假设thread3得到了执行权,拿到锁之后进来执行等待,此时活着的线程只有thread0.
* 所以thread0只能抢到执行权之后,生产面包2,将标记改为true告诉消费者有面包可以消费了。
* 接下来执行notify唤醒,此时唤醒休眠中的3个线程中的任何一个都有可能。
* 如果唤醒了消费者thread2或者thread3中的任何一个,程序都是正常。如果此时唤醒thread1则不正常。
* 如果唤醒了thread1,此时活着的线程有thread0和thread1两个线程。
* 假设thread0又获得了执行权,判读为真有面包,则又一次执行等待。
* 接下来只有thread1线程有执行权(此时没有判断标记直接生产了,出错了),所以又生产了面包3。 在这个过程中,面包2没有被消费。
* 这就是连续生产和消费容易出现的问题。

* 原因:被唤醒的线程没有判断标记就开始执行了,导致了重复的生产和消费发生。

* 解决:被唤醒的线程必须判断标记,使用while循环标记,而不使用if判断的理由。

* 但是接下来会出现死锁,原因在于:
* 上面的程序中thread0在执行notify的时候唤醒了thread1,而此时thread2和thread3两个消费者线程都处于等待状态
* thread1在执行while判断语句之后判断为真,则执行等待,此时所有的线程都处于冻结等待状态了。

* 原因:本方线程在执行唤醒的时候又一次唤醒了本方线程,而本方线程循环判断标记又继续等待,而导致所有的线程都等待。

* 解决:本方线程唤醒对方线程, 可以使用notifyAll()方法
* 唤醒之后,既有本方,又有对方,但是本方线程判断标记之后,会继续等待,这样就有对方线程在执行。
*/
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()  + this.name);
// 将标记改为false
flag = false;
// 唤醒生产者
this.notify();
}
}

// 生产者
class Procer implements Runnable {
private Resource resource;

public Procer(Resource resource) {
this.resource = resource;
}

public void run() {
while (true) {
resource.setName("面包");
}
}
}

// 消费者
class Consumer implements Runnable {
private Resource resource;

public Consumer(Resource resource) {
this.resource = resource;
}

@Override
public void run() {
while (true) {
resource.getName();
}
}
}

热心网友 时间:2023-10-09 20:33

package ProceandCousume;

public class ProcerConsumer {
public static void main(String[] args) {
Blacket b=new Blacket();
Consumer c=new Consumer(b);
Procer p=new Procer(b);
new Thread(c).start();
new Thread(p).start();
}
}

class Food{
int id;
Food(int id){
this.id=id;
}
public String toString(){
return "food: "+id;
}
}


class Blacket {
int index=0;
Food[] food=new Food[6];

public synchronized void push(Food fd){
if(index==food.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
food[index]=fd;
index++;
}
public synchronized Food pop(){
if(index==0){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.notify();
index--;
return food[index];

}
}

class Procer implements Runnable{
Blacket b=null;
Procer(Blacket b){
this.b=b;
}
public void run(){
for (int i = 0; i < 20; i++) {
Food fd=new Food(i);
b.push(fd);
System.out.println("生产了: "+fd);
try {
Thread.sleep((int)Math.random()*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


class Consumer implements Runnable{
Blacket b=null;
Consumer(Blacket b){
this.b=b;
}
public void run(){
for (int i = 0; i < 20; i++) {
Food fd=b.pop();
System.out.println("消费了: "+fd);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

马士兵老师曾经写过这代码,给楼主参考参考。

追问恩

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
...啊?我从嘴里吐出去是直的算过肺了吗?我不会从鼻子里出去_百度... 恶心呕吐是什么? 高考数学大题应注意哪些问题呢? 高考数学可不可以用高等数学啊 高考数学 基础知识点 常见考查方式 高考数学考什么内容 一般纳税人如何交所得税 以前的QQ忘记密码了那时候不要了就不找回密码了,现在想找回来,但是又没... 常州机场坐飞机流程 常州机场大巴时刻表 ...我早上九点起飞的飞机, 然后我这的机场快线大巴到机场时70分钟,_百 ... JAVA生产者,消费者问题? 生产者消费者模式 java为什么要用while &#x2022; 利用java多线程及同步机制实现生产者-消费者模型 我写的java生产者和消费者模式为什么会报异常呢 Java线程生产者消费者问题 求Java大神。。 多线程编程。 编写生产者|消费 诸君,求yanmu的下载地址。 java中关于消费者和生产者的问题? 看看下面这张图片出自哪部动漫。。。 Java线程生产者与消费者 学习unity的发展前景咋样? java中哪些类可以快速的编写生产者消费者模型 东方小镇的艳姆合集的解压密码是多少?求大神说下。 java Thread生产者与消费者模型 艳姆动漫哪里可以看 java 生产者消费者是设计模式吗 JAVA模拟生产者与消费者实例 unity适合哪个年龄阶段的人学? 如何学好unity 开学黑板报(初一第一学期)的内容,,,快!!!1:20前!!!有追加! java 多线程 生产者-消费者问题 关于Java多线程实现生产者和消费者的问题 java 生产者与消费者 的简单问题 java实现生产者消费者问题 在下面的注释处补充代码 急用 java多生产者-多消费者问题(+高分哦!) 找长沙中南大学升华公寓美团外卖的自提点 下爱奇艺全网影视下载 为什么爱奇艺全网影视上找到电影的简介和预告片,却没有片源? 爱奇艺视频和爱奇艺全网影视那个好用 医院能刷信用卡吗 爱奇艺全网独播的电视剧《河神》好看吗? 医院信用卡能用吗 家有娇妻(共20集)-全集在线观看–电视剧-爱奇艺全网影视 一般医院能刷信用卡吗 蜡笔小新新番(更新至845集)-全集在线观看–动漫-爱奇艺全网影视 深圳市中医院付款能不能用信用卡 笔记本散热器对电脑的效果如何 笔记本散热器有效果吗? 笔记本电脑散热器效果如何?能否有效的降低CPU及显卡的温度? 笔记本散热器效果好吗,能起到降温作用吗?