生产者与消费者问题是线程模型中的经典问题,假设生产者和消费者分别是两个类,两个类之间互相调用存在着依赖关系,如果一个类被改变将会影响另外一个类。需要一个商品缓冲区来实现解耦由生产者线程生产出一个商品之后将由消费者线程开始消费。
生产者与消费者模型实现思路如下图:
首先创建商品类,用于搭建消费者与生产者之间的缓冲区。
public class Goods {
private final String id;
private final String name;
public Goods(String id,String name){
this.id=id;
this.name=name;
}
public String getId(){
return id;
}
public String getName(){
return name;
}
public String toString() {
return "Goods{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
接下来创建生产者和消费者模型。
生产者模型完成的业务如下:
(1)生产商品;
(2)将生产的商品添加到容器;
(3)如果容器已经满了,等待消费(等通知);
class MyProducter implements Runnable{
private final Queue<Goods> queue;
//容器最大容量
private final Integer maxCapacity = 10;
//商品id编号
private final AtomicInteger id = new AtomicInteger(0);
public MyProducter(Queue<Goods> queue) {
this.queue = queue;
}
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(this.queue) {
//容器已满则等待
if (this.queue.size() == maxCapacity) {
//wait
System.out.println(Thread.currentThread().getName() + " 容器满了 等待消费");
try {
this.queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
//容器未满则继续生产
Goods goods = new Goods(
String.valueOf(id.getAndIncrement()),
"商品"
);
System.out.println(Thread.currentThread().getName() + " 生产商品 " + goods);
this.queue.add(goods);
}
}
}
}
}
消费者模型完成的业务如下:
(1)消费商品;
(2)从容器中取出商品;
(3)如果容器为空,通知生产者生产;
class MyConsumers implements Runnable{
private final Queue<Goods> queue;
public MyConsumers(Queue<Goods> queue) {
this.queue = queue;
}
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(this.queue) {通知生产者生产
//容器为空,
if (this.queue.isEmpty()) {
System.out.println(Thread.currentThread().getName() + " 容器已空 通知生产");
this.queue.notifyAll();
} else {
//否则继续消费
Goods goods = this.queue.poll();
if (goods != null) {
System.out.println(Thread.currentThread().getName() + " 消费商品 " + goods);
}
}
}
}
}
}
最后就是完成测试类,具体创建如下:
public class testConsumerAndProducter {
public static void main(String[] args){
//容器
final Queue<Goods> queue=new LinkedList<>();
//生产者业务类
final Runnable produce=new MyProducter(queue);
//消费者业务类
final Runnable customer=new MyConsumers(queue);
//生产者线程
for(int i=0;i<5;i++){
new Thread(produce,"Thread-Produce-"+i).start();
}
//消费者线程
for(int i=0;i<5;i++) {
new Thread(customer,"Thread-Customer-"+i).start();
}
}
}