生产者和消费者三种实现

1、syncronized+wait+notify

package com.rrfare.producerconsumer;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;

public class OrderManager {

    // 容器最大值
    private static final int MAX_COUNT = 5;
    // 容器(这里不使用BlockingQueue,而是使用线程不安全的LinkedList,并结合syncronized保证线程安全)
    private Queue<Order> orderQueue = new LinkedList<Order>();
    private Random random = new Random();


    public static void main(String[] args) {
        OrderManager shareObj = new OrderManager();

        Thread produceThread = new Thread(new ProducerThread(shareObj));
        Thread produceThread2 = new Thread(new ProducerThread(shareObj));
        produceThread.start();
        produceThread2.start();

        Thread consumerThread = new Thread(new ConsumeThread(shareObj));
        Thread consumerThread2 = new Thread(new ConsumeThread(shareObj));
        consumerThread.start();
        consumerThread2.start();
    }


    public synchronized void addOrder(){
        while(orderQueue.size() >= MAX_COUNT){
            try {
                System.out.println(Thread.currentThread().getName() + "队列已满,待会再生产");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        int i = random.nextInt(1000);
        Order tempOrder = new Order(i,"order"+i);
        orderQueue.offer(tempOrder);  // use prefer to add
        System.out.println(Thread.currentThread().getName() + "--produce order--" + tempOrder);
        notifyAll();
    }

    public synchronized void takeOrder(){
        while(orderQueue.size() < 1){
            try {
                System.out.println(Thread.currentThread().getName() + "队列已空,等待生产");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        Order tempOrder = orderQueue.poll(); // use prefer to remove
        System.out.println(Thread.currentThread().getName() + "--consume order--" + tempOrder);
        notifyAll();
    }
}

class ProducerThread implements Runnable {

    private OrderManager orderManager;
    public  ProducerThread(OrderManager orderManager) {
        this.orderManager = orderManager;
    }

    @Override
    public void run() {
        while(true){
            orderManager.addOrder();
        }
    }
}

class ConsumeThread implements Runnable {
    private OrderManager orderManager;
    public  ConsumeThread(OrderManager orderManager) {
        this.orderManager = orderManager;
    }
    @Override
    public void run() {
        while(true){
            orderManager.takeOrder();
        }
    } 
}

2、BlockingQueue

public class UseBlockQueue {

    /**
     * 队列元素数量达到指定容量时会阻塞生产者线程,消费者消费数据时,生产者线程又被唤醒
     * LinkedBlockingQueue实现中生产者和消费者使用了不同的锁,消费者和生产者可以并发处理队列中数据,因此可以用于高并发应用中
     * 注意:默认构造时会创建一个无限大队列,这样如果生产者速度一旦大于消费者,就会导致资源慢慢耗尽,因此构造时最好显式指定容量
     */
    private static BlockingQueue<Order> orderQueue = new LinkedBlockingQueue<Order>(10);  // BlockingQueue内部实现了同步细节,直接使用很方便

    /**
     * 内部维护一个定长数组
     * ArrayBlockingQueue在生产者放入数据和消费者获取数据,都是共用同一个锁对象,导致生产者和消费者无法并行操作数据
     * ArrayBlockingQueue和LinkedBlockingQueue重要区别在于,前者在插入或删除元素时不会产生或销毁任何额外的对象实例,
     * 而后者则会生成一个额外的Node对象。这在长时间内需要高效并发地处理大批量数据的系统中,对于GC的影响存在一定的区别
     */
    private static BlockingQueue<Order> orderQueue2 = new ArrayBlockingQueue<Order>(10);


    public static void main(String[] args) {
        Thread produceThread = new Thread(new ProducerThread(orderQueue));
        Thread consumerThread1 = new Thread(new ConsumerThread(orderQueue));
        Thread consumerThread2 = new Thread(new ConsumerThread(orderQueue));
        produceThread.start();
        consumerThread1.start();
        consumerThread2.start();
    }
}

class ConsumerThread implements Runnable {

    private BlockingQueue<Order> order_Queue;
    public ConsumerThread(BlockingQueue<Order> orderQueue){
        this.order_Queue = orderQueue;
    }

    @Override
    public void run() {
        while(true){
            Order tempOrder = null;
            try {
                tempOrder = order_Queue.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"--consume order--" + tempOrder);
        }
    }
}

class ProducerThread implements Runnable {

    private Random random = new Random();
    private BlockingQueue<Order> order_Queue;
    public  ProducerThread(BlockingQueue<Order> orderQueue){
        this.order_Queue = orderQueue;
    }

    @Override
    public void run() {
        while(true){
            int i = random.nextInt(1000);
            Order tempOrder = new Order(i,"order"+i);
//          order_Queue.add(tempOrder);   // add和put的区别:前者在队列满之后如果继续添加会抛出异常;后者会进入阻塞状态等待消费者消费腾出空间后继续
            try {
                order_Queue.put(tempOrder);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"--produce order--" + tempOrder);
        }
    }
}

3、Redis List(Redis也支持发布订阅模式,同样可以实现生产者和消费者)

public class TestRedis {

    private static final String REDIS_ADDR = "127.0.0.1:6379:0";
    private static final String REDIS_LIST_KEY = "myList";
    private static final int MAX_COUNT = 200;
    public static void main(String[] args) {
        RedisListDao_C redisListDao = new RedisListDao_C(REDIS_ADDR);

        Thread consumerT = new Thread(new ConsumerThread(redisListDao, REDIS_LIST_KEY));
        Thread producerT = new Thread(new ProducerThread(redisListDao, REDIS_LIST_KEY,MAX_COUNT));

        producerT.start();
        consumerT.start();
    }
}

class ConsumerThread implements Runnable {
    RedisListDao_C redisDao;
    String redisListKey;

    public ConsumerThread(RedisListDao_C redisListDao,String redisListKey){
        this.redisDao = redisListDao;
        this.redisListKey = redisListKey;
    }
    public void run() {
        while(true){
            // 使用blpop,当没有订单可消费时,进入阻塞状态,超时参数设为 0 表示阻塞时间可以无限期延长(block indefinitely) 
            // blpop传入参数示例:key1 key2 key3 timeout
            // blpop返回第一个不为空的列表记录,示例:key1 value1
            List<String> value = redisDao.blpop(new String[]{redisListKey,"0"});
            if(value == null)
                continue;
            System.out.println(Thread.currentThread().getName() + "--consume--" + value.get(1));
        }
    }
}

class ProducerThread implements Runnable {
    RedisListDao_C redisDao;
    String redisListKey;
    int MAX_COUNT;
    Random random = new Random();

    public ProducerThread(RedisListDao_C redisListDao,String redisListKey,int maxCount){
        this.redisDao = redisListDao;
        this.redisListKey = redisListKey;
        MAX_COUNT = maxCount;
    }

    public void run() {
        while(true){
            String tempValue = "Order"+random.nextInt(1000);
            redisDao.rpush(redisListKey,tempValue);
            System.out.println(Thread.currentThread().getName() + "--Produce--" + tempValue);
            // 达到阈值后暂停10秒钟再生产,注意:虽然一直在生产,很容易达到200阈值,但是也一直在消费(清除)
            if(redisDao.len(redisListKey) >= MAX_COUNT){
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

4、MessageQueue

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值