1. 程式人生 > >Java執行緒協作--生產者和消費者模式

Java執行緒協作--生產者和消費者模式

    生產者消費者模式是執行緒協作的經典應用,主要由具體產品類,容器類,生產者執行緒,消費者執行緒組成。具體表現形式為生產者執行緒生產產品往容器裡放置,當容器滿的時候,生產執行緒呼叫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();
			}
			
		}
	}
	
}



執行結果: