-->

生产者与消费者问题,一个生产者多个消费者,为什么只有一个消费者参与消费?

2020-11-21 18:31发布

问题:

预计输出,
一个生产者生产 --------------------------------------------------
消费者1 消费-----------------------------------------------------

生产者生产 -------------------------------------------------------
消费者2消费--------------------------------------------------------

主方法 创建生产者消费者

public class ProAndCon {
    public static void main(String[] args) {
        List list =new ArrayList();

        ProThread proThread1=new ProThread(list);
        ProThread proThread2=new ProThread(list);
        ConThread conThread1=new ConThread(list);
        ConThread conThread2=new ConThread(list);
        proThread1.setName("生产1");

        conThread1.setName("消费1");
        conThread2.setName("消费2");

        proThread1.start();
        conThread1.start();
        conThread2.start();
    }
}
//生产线程
class ProThread extends Thread{
    private  List list;
    ProThread(List list) {
        this.list = list;
    }

    @Override
    public void run() {
        synchronized (list) {
            while (true) {
                if (list.size() > 0) {
                    try {
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                Object object = new Object();
                list.add(object);
                System.out.println(Thread.currentThread().getName() + "生产 list" + object);
                list.notifyAll();
            }
        }
    }
}
//消费线程

class  ConThread extends  Thread{
    private  List list;
    public ConThread(List list) {
        this.list=list;
    }
    @Override
    public void run() {

        while (true){
            synchronized (list){
            if (list.size()==0){
                try {
                    list.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
           Object object= list.remove(0);
            System.out.println(Thread.currentThread().getName()+"消费 list"+object);
            list.notifyAll();
        }
    }
    }
}

出现问题,一直就是单个生产者,单个线程消费者,多次运行,变换消费者,单还是一直一个消费者

回答1:

因为wait和notifyAll的机制,list.wait只有持有list锁的对象才能调用,list.notifyAll只会唤醒调用由list锁调用wait进入等待的线程。
所以你的程序是这样运行的(这里假设生产者先拿到锁,其他几种情况的问题都和下面一样):
1.消费者1和消费者2和生产者1在第一次时竞争锁,假设生产者先拿到锁,处理后,唤醒所有list锁调用的等待线程,然后再因list.size>0进入等待状态,释放锁。
2.这时俩个消费者互相竞争,假设消费者1拿到锁,处理后,唤醒所有list锁调用的等待线程(这里是生产者),注意这时消费者1还没有释放锁,直到循环到判断语句,因list.size=0进入等待状态,才释放锁。
3.生产者被唤醒,拿到锁,继续处理,处理后,唤醒所有list锁调用的等待线程(这里只会唤醒消费者1,因为消费者2根本没有机会拿到锁去调用list.wait),然后再因list.size>0进入等待状态,释放锁。
可以发现只有第一波消费者之间的竞争是平衡,当第一波过后,抢不到锁的消费者就再也拿不到锁了,因为notifyAll只会唤醒调用由list锁调用wait进入等待的线程,而wait方法只有获取到锁是才能去调用。(语文不好,有点绕,希望看得懂)



回答2:

建议代码好好格式化一下,看着太乱了。这个编辑器是支持格式化代码的



回答3:

https://www.cnblogs.com/moongeek/p/7631447.html

notifyAll的唤醒源代码分析: https://blog.csdn.net/lxbjkben/article/details/79386492?utm_source=blogxgwz6



回答4:

你这个代码生产者生产一个产品后就会阻塞自己直到一个消费者消费了产品,消费者消费一个产品就会阻塞自己直到生产者生产了一个产品。所以一直都是生产者生产一个,消费者消费一个。
可以改为产品数量小于一个值生产者再生产,产品数量不为0消费者再消费



标签: java