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


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

    本科的时候写的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();
     
        }
    }
  • 相关阅读:
    hdu4355(三分求极值)
    Codeforces Round #107 (Div. 1) (快速求质因子、vector)
    2012哈工程ACM暑期集训图论专场(练习赛第7场)题解
    2012 MultiUniversity Training Contest 6
    Codeforces Beta Round #97 (Div. 2)
    Codeforces Round #134 (Div. 2) 并查集
    C++ Boost foreach
    Design : 如何设计View
    15个最优秀的酒店网页免费模板
    在C++中使用tr1实现functor/函数指针/成员函数指针
  • 原文地址:https://www.cnblogs.com/samanian/p/11981142.html
Copyright © 2020-2023  润新知