生产者/消费者模式的实现

经典的操作系统实验题目:生产者消费者实验

本科的时候写的C语言版本,只是通过信号量机制来保证互斥的访问,这次用Java来写完全是一个全新的理解。

 一个生产者一个消费者:

情形1:生产者负责生产商品,生产完一件商品就会停止生产,消费者负责消费产品,消费掉一件商品之后就会停止消费,等待生产。

GIthub代码

main方法:

        String lock = new String();
        P p = new P(lock);
        C c = new C(lock);
        ThreadP pThread = new ThreadP(p);
        ThreadC cThread = new ThreadC(c);
        pThread.start();
        cThread.start();

运行结果:

仓库为空,生产者开始生产—代号:1575509334730_28388903225180
生产结束了!
有商品了,可以进行消费了!  1575509334730_28388903225180
消费结束了!
仓库为空,生产者开始生产—代号:1575509334730_28388903262202
生产结束了!
有商品了,可以进行消费了!  1575509334730_28388903262202
消费结束了!
......

可以看出他们是交替运行的,如果是多生产者和多消费者情况下可能会出现都在等待的状态,出现“假死”现象。

情形2:生产者可以一直生产商品,仓库的容量为n,生产的时候不可以进行消费。即:

  • 在缓冲区为空时,消费者不能再进行消费
  • 在缓冲区为满时,生产者不能再进行生产
  • 在一个线程进行生产或消费时,其余线程不能再进行生产或消费等操作,即保持线程间的同步
  • 注意条件变量与互斥锁的顺序

在情形2的代码实现之前先看一个案例,当我们试图使用情形一的思路拓展到情形二时会出现下面的案例。

生产者消费者多线程假死的案例:

假死的原因是notify连续唤醒了同类,多消费者多生产者情况下,消费者消费后连续得唤醒了消费者,生产者生产后连续得唤醒了生产者,就会出现进程假死的情况,这种情况下需要使用notifyall方法。因为notify方法是随机唤醒一个线程的,所以会消费者唤醒消费者,消费者唤醒生产者,生产者唤醒消费者,生产者唤醒生产者,当「生产者唤醒生产者」与「消费者唤醒消费者」的情形积少成多时,就会出现假死的案例。所以通过使用notifyall来唤醒全部的线程,避免来出现上述的情况。

public class MyStack {
    private List list = new ArrayList();
 
    synchronized public void push() {
        try {
            while (list.size() == 1) {
                this.wait();
            }
            list.add("anyString=" + Math.random());
            this.notifyAll();
            System.out.println("push=" + list.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 
    synchronized public String pop() {
        String returnValue = "";
        try {
            while (list.size() == 0) {
                System.out.println("pop操作中的:"
                        + Thread.currentThread().getName() + " 线程呈wait状态");
                this.wait();
            }
            returnValue = "" + list.get(0);
            list.remove(0);
            this.notifyAll();
            System.out.println("pop=" + list.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return returnValue;
    }
}


public class P {
    private MyStack myStack;
 
    public P(MyStack myStack) {
        super();
        this.myStack = myStack;
    }
 
    public void pushService() {
        myStack.push();
    }
}


public class C {
    private MyStack myStack;
 
    public C(MyStack myStack) {
        super();
        this.myStack = myStack;
    }
 
    public void popService() {
        System.out.println("pop=" + myStack.pop());
    }
}


public class P_Thread extends Thread {
    private P p;
 
    public P_Thread(P p) {
        super();
        this.p = p;
    }
 
    @Override
    public void run() {
        while (true) {
            p.pushService();
        }
    }
}


public class C_Thread extends Thread {
    private C r;
 
    public C_Thread(C r) {
        super();
        this.r = r;
    }
 
    @Override
    public void run() {
        while (true) {
            r.popService();
        }
    }
}


public class Run {
    public static void main(String[] args) {
        MyStack myStack = new MyStack();
        P p1 = new P(myStack);
        P p2 = new P(myStack);
        P p3 = new P(myStack);
        P p4 = new P(myStack);
        P p5 = new P(myStack);
        P p6 = new P(myStack);
        P_Thread pThread1 = new P_Thread(p1);
        P_Thread pThread2 = new P_Thread(p2);
        P_Thread pThread3 = new P_Thread(p3);
        P_Thread pThread4 = new P_Thread(p4);
        P_Thread pThread5 = new P_Thread(p5);
        P_Thread pThread6 = new P_Thread(p6);
        pThread1.start();
        pThread2.start();
        pThread3.start();
        pThread4.start();
        pThread5.start();
        pThread6.start();
 
        C r1 = new C(myStack);
        C r2 = new C(myStack);
        C r3 = new C(myStack);
        C r4 = new C(myStack);
        C r5 = new C(myStack);
        C r6 = new C(myStack);
        C r7 = new C(myStack);
        C r8 = new C(myStack);
        C_Thread cThread1 = new C_Thread(r1);
        C_Thread cThread2 = new C_Thread(r2);
        C_Thread cThread3 = new C_Thread(r3);
        C_Thread cThread4 = new C_Thread(r4);
        C_Thread cThread5 = new C_Thread(r5);
        C_Thread cThread6 = new C_Thread(r6);
        C_Thread cThread7 = new C_Thread(r7);
        C_Thread cThread8 = new C_Thread(r8);
        cThread1.start();
        cThread2.start();
        cThread3.start();
        cThread4.start();
        cThread5.start();
        cThread6.start();
        cThread7.start();
        cThread8.start();
 
    }
}

 

posted @ 2019-12-05 10:10  一位神秘丐帮  阅读(430)  评论(0编辑  收藏  举报