欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多线程设计模式之——Producer-Consumer Pattern

程序员文章站 2022-07-09 09:01:12
...
此模式是在生产者与消费者之间加入一个“桥梁参与者”来缓冲线程之间的处理速度差。一般可以存在多个生产者与消费者,但当双方都只有一个的时候,又称为Pipe Pattern。

例子:假设有2个生产者,2个消费者,仓库里只能放4个产品。(这里的产品就是String类型的名字而已)


//Storage.java
public class Storage {
	private String[] buffer;
	private int head;//取走一个商品的位置
	private int tail;//存入一个商品的位置
	private int count;//buffer内的商品数量
	
	public Storage(int count){
		this.buffer = new String[count];
		this.count = 0;
		this.head = 0;
		this.tail = 0;
	}
	
	//这里的if警戒条件就运用了Guarded Suspension Pattern,要求不满足条件,便等待
	public synchronized void put(String goods) throws InterruptedException{
		System.out.println(Thread.currentThread().getName() + " produce the goods:" + goods);
		if(count >= buffer.length){
			System.out.println("the storage is full!");
			wait();
		}
		buffer[tail] = goods;
		tail = (tail + 1) % buffer.length;
		count++;
		notifyAll();
	}
	
	public synchronized String get() throws InterruptedException{
		if(count <= 0){
			System.out.println("the storage is empty!");
			wait();
		}
		String goods = buffer[head];
		head = (head + 1) % buffer.length;
		count--;
		notifyAll();
		System.out.println(Thread.currentThread().getName() + " consume the goods:" + goods );
		return goods;
	}

}




//ProducerThread.java
import java.util.Random;


public class ProducerThread extends Thread {
	private Storage storage;
	private Random random;
	private static int pid;  //产品编号
	
	public ProducerThread(String name , Storage storage){
		super(name);
		this.storage = storage;
		this.random = new Random();
	}
	
	public void run(){
		try{
			for(int i=0; i<10; i++){
				Thread.sleep(random.nextInt(1000));//模拟生产时间
				String goods = getName() + " produce the goods" + nextPId();
				storage.put(goods);
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}
	
	private static synchronized int nextPId(){
		return pid++;
	}

}




//ConsumerThread.java
import java.util.Random;


public class ConsumerThread extends Thread {
	private Storage storage;
	private Random random;
	
	public ConsumerThread(String name , Storage storage){
		super(name);
		this.random = new Random();
		this.storage = storage;
	}
	
	public void run(){
		try{
			while(true){
				storage.get();
				Thread.sleep(random.nextInt(2000));//模拟商品使用时间
			}
		}catch(InterruptedException e){
			e.printStackTrace();
		}
	}

}




//Main.java
public class Main {

	public static void main(String[] args) {
		Storage storage = new Storage(4);
		new ProducerThread("producer_lulu01" , storage).start();
		new ProducerThread("producer_lulu02" , storage).start();
		new ConsumerThread("consumer_fang01" , storage).start();
		new ConsumerThread("consumer_fang02" , storage).start();
		

	}

}