Java多种方式实现生产者消费者模式

生产消费者模式

生产者消费者问题(Producer-consumer problem),也称有限缓冲问题(Bounded-buffer problem),是一个多线程同步问题的经典案例。生产者生成一定量的数据放到缓冲区中,然后重复此过程;与此同时,消费者也在缓冲区消耗这些数据。生产者和消费者之间必须保持同步,要保证生产者不会在缓冲区满时放入数据,消费者也不会在缓冲区空时消耗数据。不够完善的解决方法容易出现死锁的情况,此时进程都在等待唤醒。

示意图:
在这里插入图片描述

实现方式

实现的核心
   保证同一资源被多个线程并发访问时的完整性。常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。

Java能实现的几种方法

  1. wait() / notify()方法
  2. await() / signal()方法
  3. BlockingQueue阻塞队列方法
  4. 信号量(待更新)

Container.java

package com.mars.sample;
public interface Container<E> {
	public E get();
	public void put(E e);
	public int capacity();
}
1、wait() / notify()方式
package com.mars.sample;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

public class WaitContainer<E> implements Container<E> {
	private LinkedList<E> queue;
	private int capacity;
	public WaitContainer(int capacity) {
		this.queue = new LinkedList<E>();
		this.capacity = capacity;
	}
	public boolean isFull() {
		return queue.size() >= capacity();
	}
	public boolean isEmpty() {
		return queue.size() == 0;
	}
	public E get() {
		E val = null;
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		synchronized (queue) {
			while (isEmpty()) {
				try {
                    System.out.println("container is empty,waiting ...");
                    queue.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			val = queue.poll();
			queue.notify();
		}
		return val;
	}
	public void put(E e) {
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		synchronized (queue) {
			while (isFull()) {
				try {
					System.out.println("container is Full,waiting ...,size="+queue.size());
					queue.wait();
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
			queue.add(e);
			queue.notify();
		}
	}

	@Override
	public int capacity() {
		return capacity;
	}
}
2、 await() / signal()方式
package com.mars.sample;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionContainer<E> implements Container<E> {
	private LinkedList<E> queue;
	private int capacity;
	private Lock lock = new ReentrantLock();
	private Condition notFull = lock.newCondition();
	private Condition notEmpty = lock.newCondition();
	public ConditionContainer(int capacity) {
		this.queue = new LinkedList<E>();
		this.capacity = capacity;
	}

	@Override
	public E get() {
		// 消费
		E val = null;
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		lock.lock();
		try {
			while (isEmpty()) {
				try {
					System.out.println("container is empty,waiting ...");
					notEmpty.await();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			 val = queue.poll();
			notFull.signal();
		} finally {
			lock.unlock();
		}
		return val;
	}

	@Override
	public void put(E e) {
		// 生产
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		lock.lock();
		try {
			while (isFull()) {
				try {
					System.out.println("container is Full,waiting ...,size="+queue.size());
					notFull.await();
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
			queue.add(e);
			notEmpty.signal();
			
		} finally {
			lock.unlock();
		}
	}
	@Override
	public int capacity() {
		return capacity;
	}
	public boolean isFull() {
		return queue.size() >= capacity();
	}
	public boolean isEmpty() {
		return queue.size() == 0;
	}
}
3、BlockingQueue阻塞队列方式
package com.mars.sample;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

public class BlockingContainer<E> implements Container<E> {
	private BlockingQueue<E> queue;
	private int capacity;
	
	public BlockingContainer(int capacity) {
		this.queue = new ArrayBlockingQueue<E>(capacity);
		this.capacity = capacity;
	}
	
	@Override
	public E get() {
		E val = null;
		try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		try {
			val = queue.take();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return val;
	}
	@Override
	public void put(E e) {
		try {
			queue.put(e);
			System.out.println("container size="+queue.size());
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}	
	}
	@Override
	public int capacity() {
		return capacity;
	}
}

生产者

package com.mars.sample;

import java.util.Random;

public class Producer implements Runnable {

	private Container<Integer> container;
	public Producer(Container<Integer> container) {
		this.container = container;
	}
	@Override
	public void run() {
		while(true) {
			Integer val = new Random().nextInt(100);
			container.put(val);
			System.out.println("Producer--" + Thread.currentThread().getName() + "--put:" + val);
		}
	}
}

消费者

package com.mars.sample;

public class Consumer implements Runnable {

	private Container<Integer> container;

	public Consumer(Container<Integer> container) {
		this.container = container;
	}

	@Override
	public void run() {
		while(true) {
			Integer val = container.get();
			System.out.println("consumer--" + Thread.currentThread().getName() + "--take:" + val);
		}
	}

}

主函数

package com.mars.sample;

public class Main {
	public static void main(String[] args) {
		//wait() / notify()方式
		Container<Integer> container = new WaitContainer<>(5);
		for (int i = 0; i < 5; i++) {
			new Thread(new Producer(container), "ProducerWait").start();
		}
		for (int i = 0; i < 2; i++) {
			new Thread(new Consumer(container), "ConsumerWait").start();
		}
		//await() / signal()方式
		container = new ConditionContainer<>(5);
		for (int i = 0; i < 5; i++) {
			new Thread(new Producer(container), "ProducerCondition").start();
		}
		for (int i = 0; i < 2; i++) {
			new Thread(new Consumer(container), "ConsumerCondition").start();
		}
		
		//BlockingQueue阻塞队列方式
		container = new BlockingContainer<>(5);
		for (int i = 0; i < 5; i++) {
			new Thread(new Producer(container), "ProducerBlocking").start();
		}
		for (int i = 0; i < 2; i++) {
			new Thread(new Consumer(container), "ConsumerBlocking").start();
		}
		
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值