面试:手写代码生产者和消费者实现

生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据。
 
1. 使用阻塞队列实现生产者消费者模式

生产者:

 1 public class Producer implements Runable{
 2     private final BlockingQueue sharedQueue;
 3     public Producer(BlockingQueue sharedQueue){
 4     this.sharedQueue = sharedQueue;
 5     }
 6     
 7     publlic void run(){
 8     for(i=0;i<10;i++){
 9         try{
10             System.out.println("Producer:"+i);
11             sharedQueue.put(i);
12             }catch(InterruptedException ex){
13                 System.out.println("exception:"+ex);
14               }
15             }
16     }
17 }          

消费者:

public class Consumer implements Runable{
        private final BlockingQueue sharedQueue;
        public Consumer(BlockingQueue sharedQueue){
            this.sharedQueue = sharedQueue 
        }
        
        public void run(){
             while(true){
                try{
                        System.out.println("Consumed:"+sharedQueue.take());
                }catch(InterruptedException ex){
                        System.out.println("Exception:"+ex);
                }
             }
        }
}

生产者消费者模式:

public class ProducerConsumerPattern {
    private static final Logger logger = 
    public static void main(String[] args) {
        //阻塞队列
        BlockingQueue sharedQueue = new LinkedBlockingDeque();

        //创建生产者和消费者,共享队列
        Thread prodThread = new Thread(new Producer(sharedQueue));
        Thread consThread = new Thread(new Consumer(sharedQueue));

        //开启生产者和消费者进程
        prodThread.start();
        consThread.start();
    }
}

BlockingQueue是一个阻塞队列,它的存取可以保证只有一个线程在进行,所以根据逻辑,生产者在内存满的时候进行等待,并且唤醒消费者队列,反过来消费者在饥饿状态下等待并唤醒生产者进行生产。

2. wait/notify方法实现

/**
 * 生产者消费者模式:使用Object.wait() / notify()方法实现
 */
public class ProducerConsumer {
    private static final int CAPACITY = 5;

    public static void main(String args[]){
        Queue<Integer> queue = new LinkedList<Integer>();

        Thread producer1 = new Producer("P-1", queue, CAPACITY);
        Thread producer2 = new Producer("P-2", queue, CAPACITY);
        Thread consumer1 = new Consumer("C1", queue, CAPACITY);
        Thread consumer2 = new Consumer("C2", queue, CAPACITY);
        Thread consumer3 = new Consumer("C3", queue, CAPACITY);

        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
        consumer3.start();
    }

    /**
     * 生产者
     */
    public static class Producer extends Thread{
        private Queue<Integer> queue;
        String name;
        int maxSize;
        int i = 0;

        public Producer(String name, Queue<Integer> queue, int maxSize){
            super(name);
            this.name = name;
            this.queue = queue;
            this.maxSize = maxSize;
        }

        @Override
        public void run(){
            while(true){
                synchronized(queue){
                    while(queue.size() == maxSize){
                        try {
                            System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
                            queue.wait();
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                    System.out.println("[" + name + "] Producing value : +" + i);
                    queue.offer(i++);
                    queue.notifyAll();

                    try {
Thread.sleep(
new Random().nextInt(1000));//模拟随机生产 } catch (InterruptedException e) { e.printStackTrace(); } } } } } /** * 消费者 */ public static class Consumer extends Thread{ private Queue<Integer> queue; String name; int maxSize; public Consumer(String name, Queue<Integer> queue, int maxSize){ super(name); this.name = name; this.queue = queue; this.maxSize = maxSize; } @Override public void run(){ while(true){ synchronized(queue){ while(queue.isEmpty()){ try { System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer"); queue.wait(); } catch (Exception ex) { ex.printStackTrace(); } } int x = queue.poll(); System.out.println("[" + name + "] Consuming value : " + x); queue.notifyAll(); try { Thread.sleep(new Random().nextInt(1000));//模拟随机消费 } catch (InterruptedException e) { e.printStackTrace(); } } } } } }
  • wait():当缓冲区已满/空时,生产者/消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让其他线程执行。
  • notify():当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。
3. 使用Lock和Condition的await() / signal()方法
/**
 * 生产者消费者模式:使用Lock和Condition实现
 * {@link java.util.concurrent.locks.Lock}
 * {@link java.util.concurrent.locks.Condition}
 */
public class ProducerConsumerByLock {
    private static final int CAPACITY = 5;
    private static final Lock lock = new ReentrantLock();
    private static final Condition fullCondition = lock.newCondition();     //队列满的条件
    private static final Condition emptyCondition = lock.newCondition();        //队列空的条件


    public static void main(String args[]){
        Queue<Integer> queue = new LinkedList<Integer>();

        Thread producer1 = new Producer("P-1", queue, CAPACITY);
        Thread producer2 = new Producer("P-2", queue, CAPACITY);
        Thread consumer1 = new Consumer("C1", queue, CAPACITY);
        Thread consumer2 = new Consumer("C2", queue, CAPACITY);
        Thread consumer3 = new Consumer("C3", queue, CAPACITY);

        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
        consumer3.start();
    }

    /**
     * 生产者
     */
    public static class Producer extends Thread{
        private Queue<Integer> queue;
        String name;
        int maxSize;
        int i = 0;

        public Producer(String name, Queue<Integer> queue, int maxSize){
            super(name);
            this.name = name;
            this.queue = queue;
            this.maxSize = maxSize;
        }

        @Override
        public void run(){
            while(true){

                //获得锁
                lock.lock();
                while(queue.size() == maxSize){
                    try {
                        System.out .println("Queue is full, Producer[" + name + "] thread waiting for " + "consumer to take something from queue.");
                        //条件不满足,生产阻塞
                        fullCondition.await();
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
                System.out.println("[" + name + "] Producing value : +" + i);
                queue.offer(i++);

                //唤醒其他所有生产者、消费者
                fullCondition.signalAll();
                emptyCondition.signalAll();

                //释放锁
                lock.unlock();

                try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    /**
     * 消费者
     */
    public static class Consumer extends Thread{
        private Queue<Integer> queue;
        String name;
        int maxSize;

        public Consumer(String name, Queue<Integer> queue, int maxSize){
            super(name);
            this.name = name;
            this.queue = queue;
            this.maxSize = maxSize;
        }

        @Override
        public void run(){
            while(true){
                //获得锁
                lock.lock();

                while(queue.isEmpty()){
                    try {
                        System.out.println("Queue is empty, Consumer[" + name + "] thread is waiting for Producer");
                        //条件不满足,消费阻塞
                        emptyCondition.await();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                int x = queue.poll();
                System.out.println("[" + name + "] Consuming value : " + x);

                //唤醒其他所有生产者、消费者
                fullCondition.signalAll();
                emptyCondition.signalAll();

                //释放锁
                lock.unlock();

                try {
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
4. 总结

实现生产者消费者模式有3点:

1. 拿什么作为缓冲区,给生产者和消费者解耦,平衡了生产者和消费者的处理能力。一般使用队列

2. 构建生产者,队列满使得生产者线程阻塞

3. 构建消费者 ,队列空使得消费者现成阻塞

参考:https://blog.csdn.net/u010983881/article/details/78554671

转载于:https://www.cnblogs.com/nicoleljc/p/9980632.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值