生产者与消费者模式
生产者消费者问题是一个多线程同步的经典问题,这个问题描述了生产者线程和消费者线程共享固定大小的缓冲区的问题。生产者不断的向缓冲区添加数据,消费者不断的消费缓冲区的数据,这个问题的关键是:
保证生产者在缓冲区满的时候不再向缓冲区添加数据,消费者在缓冲区空的时候也不会的时候消费缓冲区数据
解决思路:
- 生产者不断的生产,直到缓冲区满的时候,阻塞生产者线程,缓冲区不满的时候,继续生产
- 消费者不断的消费,直到缓冲区空的时候,阻塞消费者线程,缓冲区不空的时候,继续消费
使用wait,notify方式实现
public class ProducerAndConsumer {
//消费者
static class Consumer implements Runnable {
private List<Integer> queue;
public Consumer(List<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (true) {
synchronized (queue) {
while (queue.isEmpty()) {
System.out.println("Queue is Empty");
queue.wait();
}
int i = queue.remove(0);
queue.notifyAll();
System.out.println(Thread.currentThread().getName() + "消费了:" + i + "还剩:" + queue.size());
Thread.sleep(100);
}
}
} catch (InterruptedException e) {
}
}
}
//生产者
static class Producer implements Runnable {
private List<Integer> queue;
private int length; //容量
public Producer(List<Integer> queue, int length) {
this.queue = queue;
this.length = length;
}
@Override
public void run() {
try {
while (true) {
synchronized (queue) {
while (queue.size() > length) {
queue.wait();
}
queue.add(1);
System.out.println(Thread.currentThread().getName() + "生产了" + 1 + "现在有" + queue.size());
Thread.sleep(100);
queue.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
List<Integer> queue = new ArrayList<>();
int length = 10;
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new Producer(queue, 10));
service.execute(new Producer(queue, 10));
service.execute(new Producer(queue, 10));
service.execute(new Consumer(queue));
service.execute(new Consumer(queue));
service.execute(new Consumer(queue));
}
}
使用Lock接口的await,signal方式实现
public class ProducerAndConsumer1 {
private static ReentrantLock lock = new ReentrantLock();
private static Condition empty = lock.newCondition();
private static Condition full = lock.newCondition();
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
ExecutorService servie = Executors.newCachedThreadPool();
int maxLength = 10;
servie.execute(new Consumer(list,lock));
servie.execute(new Consumer(list,lock));
servie.execute(new Consumer(list,lock));
servie.execute(new Producer(list,10,lock));
servie.execute(new Producer(list,10,lock));
servie.execute(new Producer(list,10,lock));
}
static class Consumer implements Runnable {
private List<Integer> list;
private Lock lock;
public Consumer(List<Integer> list,Lock lock) {
this.list = list;
this.lock = lock;
}
@Override
public void run() {
while (true) {
lock.lock();
try {
while (list.isEmpty()) {
System.out.println("消费者" + Thread.currentThread().getName() + " list为空,进行wait");
empty.await();
}
Integer element = list.remove(0);
System.out.println("消费者" + Thread.currentThread().getName() + " 消费数据:" + element);
full.signalAll();
Thread.sleep(500);
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
static class Producer implements Runnable {
private List<Integer> list;
private int maxLength;
private Lock lock;
public Producer(List<Integer> list,int maxLength,Lock lock) {
this.lock = lock;
this.list = list;
this.maxLength = maxLength;
}
@Override
public void run() {
while (true) {
lock.lock();
try {
while (list.size() >= maxLength) {
System.out.println("生产者" + Thread.currentThread().getName() + " list以达到最大容量,进行wait");
full.await();
}
Random random = new Random();
int i = random.nextInt();
System.out.println("生产者" + Thread.currentThread().getName() + " 生产数据" + i);
list.add(i);
empty.signalAll();
Thread.sleep(500);
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
}
}
使用BlockingQueue的方式实现
public static void main(String[] args) {
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
ExecutorService service = Executors.newCachedThreadPool();
service.execute(new Consumer(queue));
service.execute(new Consumer(queue));
service.execute(new Consumer(queue));
service.execute(new Producer(queue));
service.execute(new Producer(queue));
service.execute(new Producer(queue));
}
static class Producer implements Runnable {
private BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (true) {
Thread.sleep(20);
queue.put(new Random().nextInt());
System.out.println(Thread.currentThread().getName() + "生产:" + queue.size());
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Consumer implements Runnable {
private BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (true) {
Thread.sleep(new Random().nextInt(1000));
queue.take();
System.out.println(Thread.currentThread().getName() + "消费:" + queue.size());
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}