1.生产者生产数据到缓冲区中,消费者从缓冲区中取数据。
2.如果缓冲区已经满了,则生产者线程阻塞。
3.如果缓冲区为空,那么消费者线程阻塞。
实际上还有一种await、signalAll的实现方式,这里我排除了,因这里需要涉及到concurrent包下Lock的东西,精力有限,重点在于设计模式的理解,所以暂时TODO。
这里只实现sychronized和bloackQueue的例子。
我直接贴出三个角色的代码,然后测试的时候我刻意让消费速度小于生产速度。
产品池,封装了存和取俩个方法以便让生产者和消费者使用。
为什么它不是一个Thread的子类也能wait和notify,因为wait和notify是Object的方法。
package com.zj.dp.生产者消费者模式.wait_notify;
public class BufferArea {
//当前资源数量的记数值
private int currNum = 0;
//资源池中允许存放的资源数目
private int maxSize = 10;
/**
* 从资源池中取走资源
*/
public synchronized void get() {
if (currNum > 0) {
currNum--;
System.out.println("Cosumer__" + Thread.currentThread().getName() + "消耗一件资源," + "当前缓冲区有" + currNum + "个");
//通知生产者生产资源
notifyAll();
} else {
try {
//如果没有资源,则Cosumer__进入等待状态
System.out.println("Cosumer__" + Thread.currentThread().getName() + ":当前缓冲区资源不足,进入等待状态");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 向缓冲区中添加资源
*/
public synchronized void put() {
//若当前缓冲区内的资源计数小于最大size数,才加
if (currNum < maxSize) {
currNum++;
System.out.println(Thread.currentThread().getName() + "生产一件资源,当前资源池有"+ currNum + "个");
//通知等待的消费者
notifyAll();
} else {
//若当前缓冲区内的资源计数大于最大size数,则等待
try {
System.out.println(Thread.currentThread().getName() + "线程进入等待 << 当前缓冲区内的资源计数大于最大size数");
wait();//生产者进入等待状态,并释放锁
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者,代码很简单。
package com.zj.dp.生产者消费者模式.wait_notify;
public class Consumer extends Thread {
private BufferArea mBufferArea;
public Consumer(BufferArea bufferArea) {
this.mBufferArea = bufferArea;
setName("Consumer_"+getName());
}
@Override
public void run() {
//不断的取出资源
while (true) {
sleepSomeTime();
mBufferArea.get();
}
}
private void sleepSomeTime() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
生产者,代码很简单。
package com.zj.dp.生产者消费者模式.wait_notify;
public class Producer extends Thread {
private BufferArea mBufferArea;
public Producer(BufferArea bufferArea){
this.mBufferArea = bufferArea;
setName("Producer_"+getName());
}
@Override
public void run() {
//不断地生产资源
while(true){
sleepSomeTime();
mBufferArea.put();
}
}
private void sleepSomeTime() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出结果:
Producer_Thread-4生产一件资源,当前资源池有1个
Producer_Thread-3生产一件资源,当前资源池有2个
Producer_Thread-5生产一件资源,当前资源池有3个
Producer_Thread-4生产一件资源,当前资源池有4个
Producer_Thread-3生产一件资源,当前资源池有5个
Producer_Thread-5生产一件资源,当前资源池有6个
Producer_Thread-3生产一件资源,当前资源池有7个
Producer_Thread-4生产一件资源,当前资源池有8个
Producer_Thread-5生产一件资源,当前资源池有9个
Producer_Thread-3生产一件资源,当前资源池有10个
Producer_Thread-5线程进入等待 << 当前缓冲区内的资源计数大于最大size数
Producer_Thread-4线程进入等待 << 当前缓冲区内的资源计数大于最大size数
Producer_Thread-3线程进入等待 << 当前缓冲区内的资源计数大于最大size数
--》讲解:先是3个生产者线程生产满了10个(maxSize)产品,然后就都进入了等待
Cosumer__Consumer_Thread-0消耗一件资源,当前缓冲区有9个
Cosumer__Consumer_Thread-2消耗一件资源,当前缓冲区有8个
Cosumer__Consumer_Thread-1消耗一件资源,当前缓冲区有7个
--》讲解:3个消费者消费了3个产品
Producer_Thread-5生产一件资源,当前资源池有8个
Producer_Thread-4生产一件资源,当前资源池有9个
Producer_Thread-3生产一件资源,当前资源池有10个
--》讲解:生产者立马又生产3个
Producer_Thread-5线程进入等待 << 当前缓冲区内的资源计数大于最大size数
Producer_Thread-4线程进入等待 << 当前缓冲区内的资源计数大于最大size数
Producer_Thread-3线程进入等待 << 当前缓冲区内的资源计数大于最大size数
--》讲解:又消费3个
Cosumer__Consumer_Thread-0消耗一件资源,当前缓冲区有9个
Cosumer__Consumer_Thread-1消耗一件资源,当前缓冲区有8个
Cosumer__Consumer_Thread-2消耗一件资源,当前缓冲区有7个
--》讲解:又生产3个 ...后续大致也就这样,子子孙孙无穷尽也...不贴了...
package com.zj.dp.生产者消费者模式.blockingqueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class BlockQueueBufferArea {
BlockingQueue mProductPoll = new LinkedBlockingQueue(10);
public void put() {
try {
System.out.println(Thread.currentThread().getName() + "产品池被放入了一个资源");
mProductPoll.put(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void get() {
try {
System.out.println(Thread.currentThread().getName() + "产品池被取走了一个资源");
mProductPoll.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.zj.dp.生产者消费者模式.blockingqueue;
public class Consumer extends Thread {
private BlockQueueBufferArea mBufferArea;
public Consumer(BlockQueueBufferArea bufferArea) {
this.mBufferArea = bufferArea;
setName("Consumer_"+getName());
}
@Override
public void run() {
//不断的取出资源
while (true) {
sleepSomeTime();
mBufferArea.get();
}
}
private void sleepSomeTime() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.zj.dp.生产者消费者模式.blockingqueue;
public class Consumer extends Thread {
private BlockQueueBufferArea mBufferArea;
public Consumer(BlockQueueBufferArea bufferArea) {
this.mBufferArea = bufferArea;
setName("Consumer_"+getName());
}
@Override
public void run() {
//不断的取出资源
while (true) {
sleepSomeTime();
mBufferArea.get();
}
}
private void sleepSomeTime() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.zj.dp.生产者消费者模式.blockingqueue;
public class Test {
public static void main(String[] args) {
BlockQueueBufferArea bufferArea = new BlockQueueBufferArea();
Consumer consumer1 = new Consumer(bufferArea);
Consumer consumer2 = new Consumer(bufferArea);
Consumer consumer3 = new Consumer(bufferArea);
Producer producer1 = new Producer(bufferArea);
Producer producer2 = new Producer(bufferArea);
Producer producer3 = new Producer(bufferArea);
consumer1.start();
consumer2.start();
consumer3.start();
producer1.start();
producer2.start();
producer3.start();
}
}
Producer_Thread-3产品池被放入了一个资源
Producer_Thread-5产品池被放入了一个资源
Producer_Thread-4产品池被放入了一个资源
Producer_Thread-3产品池被放入了一个资源
Producer_Thread-5产品池被放入了一个资源
Producer_Thread-4产品池被放入了一个资源
Producer_Thread-3产品池被放入了一个资源
Producer_Thread-4产品池被放入了一个资源
Producer_Thread-5产品池被放入了一个资源
Producer_Thread-3产品池被放入了一个资源
Producer_Thread-5产品池被放入了一个资源
Producer_Thread-4产品池被放入了一个资源
Producer_Thread-3产品池被放入了一个资源
Consumer_Thread-1产品池被取走了一个资源
Consumer_Thread-2产品池被取走了一个资源
Consumer_Thread-0产品池被取走了一个资源
Producer_Thread-4产品池被放入了一个资源
Producer_Thread-3产品池被放入了一个资源
Producer_Thread-5产品池被放入了一个资源
Consumer_Thread-0产品池被取走了一个资源
Consumer_Thread-1产品池被取走了一个资源
Consumer_Thread-2产品池被取走了一个资源
Producer_Thread-3产品池被放入了一个资源
Producer_Thread-5产品池被放入了一个资源
Producer_Thread-4产品池被放入了一个资源
https://www.cnblogs.com/fankongkong/p/7339848.html
本文Demo:https://github.com/zj614android/designPattern