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