关于线程间通信结合一点业务问题

关于线程间通信结合一点业务问题

关于线程间通信问题

问题描述:

    ​老师,我有个问题,如果增加一个业务场景,两个线程同时启动,但是生产和消费都是随机的,即使用(int)(Math.random()*10)决定,而消费需务必保证存货量足够才能进行消费,否则需要先生产足够再进行消费;而生产只受限于每一次生产的数量,那么,如何能保证,调用消费时自检,成功继续;否则消费堵塞,唤醒生产呢?

相关代码:

public class Queue {

private int n;
private boolean flag = false;

public Queue(int n){
this.n = n;
}

public synchronized void getN() {
int i = (int)(Math.random()*10);
if(!flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(this.n-i<0){
System.out.println("目前为"+this.n+",生产不够,请先生产");
flag=!flag;
}
this.n -= i;
System.out.println("消费完还剩余"+this.n);
flag=!flag;
notifyAll();
}


public synchronized void setN() {
if(flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = (int)(Math.random()*10);
this.n+=i;
System.out.println("生产完还剩余"+this.n);
flag=!flag;
notifyAll();
}
}

​public class Productor implements Runnable{

Queue queue;

public Productor(Queue queue){
this.queue = queue;
}

@Override
public void run() {
while (true){
queue.setN();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public class Consumer implements Runnable {

Queue queue;

public Consumer(Queue queue){
this.queue = queue;
}


@Override
public void run() {
while (true){
queue.getN();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
好帮手慕小脸 2021-06-02 14:05:58

同学你好,可以使用循环来判断目前剩余总量是否够消费总量,如果不够的话直接去生产,直到生产数量充足之后再继续进行消费,修改后的代码如下:

public class Queue {

private int n;
private boolean flag = false;

public Queue(int n) {
this.n = n;
}

public synchronized void getN() {
int i = (int) (Math.random() * 10);
if (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//循环判断目前剩余总量是否够消费总量,不够的话直接去生产,直到生产够才继续进行消费
while (this.n - i < 0) {
System.out.println("目前为" + this.n + ",消费不够,目前需要消费"+i+",请先生产");
flag = !flag;
setN();
}
this.n -= i;
System.out.println("消费完还剩余" + this.n);
flag = !flag;
notifyAll();
}

public synchronized void setN() {
if (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int i = (int) (Math.random() * 10);
this.n += i;
System.out.println("生产完还剩余" + this.n);
flag = !flag;
notifyAll();
}
}

​祝学习愉快~

  • 提问者 慕移动2137064 #1

    那,老师,我有个疑问,您能不能说一下,可否通过

    notify或notifyAll

    进行准确的线程进行唤醒呢?比如一个线程调用该函数,唤醒的应该是其他wait()了的线程,而不会是该线程本身,对吧?

    2021-06-02 21:18:00
  •  notifyAll()方法会唤醒所有 wait 线程,那个notify()方法只随机唤醒一个 wait 线程,你要是想指定唤醒某个线程,可以使用synchronized + wait + notify?参考这个https://www.cnblogs.com/yuarvin/p/14506437.html

    2021-06-03 10:29:14
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师