zoukankan      html  css  js  c++  java
  • 多线程面试题系列3_生产者消费者模式的两种实现方法

    题目

    生产者-消费者模式
    题目:
    写一个固定容量的同步容器,拥有put和get方法,以及getCount方法
    能够支持2个生产者线程和10个消费者线程的阻塞调用

    • 解法一:

      使用wait和notify/notifyAll实现

      需要注意的点:
      因为一个生产者只能生产一个食物,所以要想满足所有消费者必须启用数量相等的生产者线程。
      wait()方法必须由一个上锁的对象使用。
      使用notifyALL()。
      使用while配合wait()。

    class Container {
        private static final int SIZE = 10;
        volatile static int count = 0;
        Object o = new Object();
        void put() {
            synchronized(o) {
                while (getCount() == SIZE) {
                    try {
                        o.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                count++;
                System.out.println("Producer now!	" + "AFTER ALL: " + getCount());
                o.notifyAll();
            }
        }
        void get() {
            synchronized(o) {
                while (getCount() == 0) {
                    try {
                        o.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                count--;
                System.out.println("Consumer now!	" + "AFTER ALL: " + getCount());
                o.notifyAll();
            }
        }
        int getCount() {
            return count;
        }
    }
    public class Question3 {
        public static void main(String[] args) {
            Container container = new Container();
            for(int i = 0; i < 10; i++) {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        container.get();
                    }
                });
                thread.start();
            }
            try {
                Thread.sleep(2000);
            } catch(Exception e) {
                e.printStackTrace();
            }
            for(int i = 0; i < 5; i++) {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        container.put();
                    }
                });
                thread.start();
            }
        }
    }
    
    • 解法二:

    使用wait和notify/notifyAll实现

    需要注意的点:
    因为一个生产者只能生产一个食物,所以要想满足所有消费者必须启用数量相等的生产者线程。
    await()方法必须由一个上锁的ReentrantLock对象使用。
    使用while配合await()。

    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    class Container1 {
        volatile static int count = 0;
        private static final int SIZE = 10;
        ReentrantLock lock = new ReentrantLock();
        Condition condition_get = lock.newCondition();
        Condition condition_put = lock.newCondition();
        void get() {
            lock.lock();
            while(getCount() == 0) {
                try {
                    condition_get.await();
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
            count--;
            System.out.println("Consumer now!	" + "AFTER ALL: " + getCount());
            condition_put.signalAll();
            lock.unlock();
        }
        void put() {
            lock.lock();
            while(getCount() == SIZE) {
                try {
                    condition_put.await();
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
            count++;
            System.out.println("Producer now!	" + "AFTER ALL: " + getCount());
            condition_get.signalAll();
            lock.unlock();
        }
        int getCount() {
            return count;
        }
    }
    public class Question3a {
        public static void main(String[] args) {
            Container1 container1 = new Container1();
            for(int i = 0; i < 10; i++) {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        container1.get();
                    }
                });
                thread.start();
            }
            try {
                Thread.sleep(2000);
            } catch(Exception e) {
                e.printStackTrace();
            }
            for(int i = 0; i < 5; i++) {
                Thread thread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        container1.put();
                    }
                });
                thread.start();
            }
        }
    }
    
    
  • 相关阅读:
    软件工程作业-结对实验
    软件工程实践作业2
    UNIX线程之间的关系
    c中计时的几种方法
    调试器工作原理(3):调试信息
    调试器工作原理(2):实现断点
    调试器工作原理(1):基础篇
    linux的终端,网络虚拟终端,伪终端(转)
    asterisk webrtc使用SIPML5初体验
    初次使用nodejs的问题
  • 原文地址:https://www.cnblogs.com/fromneptune/p/11794216.html
Copyright © 2011-2022 走看看