生产者消费者模式是线程协作的经典应用,主要由具体产品类,容器类,生产者线程,消费者线程组成。具体表现形式为生产者线程生产产品往容器里放置,当容器满的时候,生产线程调用wait方法,使当前线程阻塞,而此时消费者线程在不断的消费容器里的产品,同时调用notifyf方法唤醒等待的生产者线程继续生产;同理,当消费者将容器内产品消费完之后,消费者线程会进入阻塞状态,而此时生产者线程在不断继续生产并唤醒消费者线程继续消费。
注:如果当前有多个线程等待一个对象,notify方法只会唤醒一个,若需要唤醒多个线程,需要调用notifyAll方法
示例代码如下:
package com.trs.thread;
import java.util.LinkedList;
/**
* Java多线程--生产者消费者模式
* @author xiayunan
* @date 2018年7月18日
*
*/
public class TestConsumerProducer {
private static DiningTable table = new DiningTable();
public static void main(String[] args) {
System.out.println("========生产者消费者模式示例开始========");
Thread t1 = new Thread(new Producer(table));
Thread t2 = new Thread(new Consumer(table));
t1.start();
t2.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("========生产者消费者模式示例结束========");
}
/**
* 肯德基全家桶
* @author xiayunan
* @date 2018年7月18日
*
*/
static class KFCBucket{
private int id;
public KFCBucket(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
/**
* 容器类--取餐台
* @author xiayunan
* @date 2018年7月18日
*
*/
static class DiningTable{
private static int index = 0;
private static int capacity = 100;
private static LinkedList<KFCBucket> list = new LinkedList<KFCBucket>();
public synchronized void offer(KFCBucket k){
while(list.size()>=DiningTable.capacity){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
list.offer(k);
System.out.println("生产了一个KFC全家桶,编号为"+k.getId()+" 产品总量为:"+DiningTable.list.size());
index++;
}
public synchronized KFCBucket poll(){
while(list.size()==0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notify();
KFCBucket bucket = list.poll();
System.out.println("消费了一个KFC全家桶,编号为"+bucket.getId()+" 产品总量为:"+DiningTable.list.size());
if(index>0){
index--;
}
return bucket;
}
}
/**
* 生产者类
* @author xiayunan
* @date 2018年7月18日
*
*/
static class Producer implements Runnable{
private DiningTable table;
public Producer(DiningTable table) {
this.table = table;
}
@Override
public void run() {
for(int i=0;i<10;i++){
table.offer(new KFCBucket(i));
}
}
}
/**
* 消费者类
* @author xiayunan
* @date 2018年7月18日
*/
static class Consumer implements Runnable{
private DiningTable table;
public Consumer(DiningTable table) {
this.table = table;
}
@Override
public void run() {
for(int i=0;i<10;i++){
table.poll();
}
}
}
}
运行结果: