其实生产者和消费者模式概念很简单,就是生产者将生产出来的产品放在仓库里,然后消费者依次从仓库里取产品消费。归到程序里,这里的仓库就可以用数组,队列或栈来表示。
掌握以下两点后,该模式的实现将不成问题。
1. 首先要明白生产者和消费者之间的并发对象就是存放产品的队列,这样才能把并发方法提炼出来。
2. 其次要掌握object.wait()和object.notifyAll()这两个方法的基本使用模式:
synchronized (object) {
//条件不成立时,则等待
while(条件不成立){
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//需要同步的代码
object.notifyAll();
}
示例1:使用LinkedList实现的FIFO方式的生产者和消费者模式,若要改为先进后出的栈方式,只需把(1)处得注释打开,替换上一语句即可。
package productor.consumer.demo.self;
import java.util.LinkedList;
public class ProductorConsumerDemo {
public static void main(String[] args) {
Queue<IPhone> queue = new Queue<IPhone>();
new Thread(new Productor("生产者1" , queue)).start();
new Thread(new Consumer("消费者1" , queue)).start();
}
}
class IPhone{
private int id;
private String name;
public IPhone(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "{id:" + id + ",name=" + name + "}";
}
}
//FIFO队列
class Queue<T>{
private static final int DEFAULT_SIZE = 8; //定义队列的默认大小
int size ; //定义队列的大小
private LinkedList<T> list = new LinkedList<T>();
public Queue() {
super();
this.size = DEFAULT_SIZE;
}
public Queue(int size) {
super();
this.size = (size <=0 ? DEFAULT_SIZE : size);
}
public synchronized void put(T t){
while(list.size() >= size){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
list.addLast(t);
System.out.println("生产了:" + t);
this.notifyAll();
}
public synchronized T get(){
while(list.size() <= 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.notifyAll();
T t = list.removeFirst();
//先进后出--同栈 t = list.removeLast(); ----(1)
System.out.println("消费了:" + t);
return t;//FIFO
}
}
//生产者
class Productor implements Runnable{
private String name;
private Queue queue;
public Productor(String name,Queue queue) {
super();
this.name = name;
this.queue = queue;
}
@Override
public void run() {
for(int i=0;i<10;i++){
IPhone iPhone = new IPhone(i,"name-" + i);
queue.put(iPhone);
try {
Thread.sleep((int) (Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者
class Consumer implements Runnable{
private String name;
private Queue queue;
public Consumer(String name,Queue queue) {
super();
this.name = name;
this.queue = queue;
}
@Override
public void run() {
for(int i=0;i<10;i++){
IPhone iPhone = (IPhone) queue.get();
try {
Thread.sleep((int) (Math.random() * 200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}