使用synchronized實現生產者消費者

 

生產者消費者程序可使用多種方法實現,有使用synchronized關鍵字,Lock對象,semaphore同步工具。今天用synchronized實現時碰到兩個問題,一個是報 IllegalMonitorStateException ,另一個是碰到死鎖。死鎖暫時解決不了。

生產者消費者有一個生產者一個消費者及多個生產者多個消費者。

一個生產者一個消費者

package cn.bj.demo.spring.javaevent.pc.sync;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 生產者消費者,假設有個傳送帶,生產者往傳送帶上放產品,消費者從傳送帶上取產品
 * 
 * */
public class ProducerAndConsumer {
	private static int MAX_SIZE = 2;  //傳送帶上最多能放產品數
	private List<Product> products = null; //傳送帶
	private ProducerTask pTask; //生產者任務
	private ConsumerTask cTask; //消費者任務
	private Producer p; //生產者
	
	public ProducerAndConsumer() {
		p = new Producer();
		products = new ArrayList<Product>();
		pTask = new ProducerTask(p, products);
		cTask = new ConsumerTask(products);
		
		Thread pThread = new Thread(pTask);
		pThread.setName("producer thread");
		pThread.start();
		
		Thread cThread = new Thread(cTask);
		cThread.setName("consumer thread");
		cThread.start();
		
		try {
			Thread.currentThread().join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("construct is over");
		
	}
	
	public static void main(String[] args) {
		
		ProducerAndConsumer pac = new ProducerAndConsumer();
	}
	
	
	class ProducerTask implements Runnable {
		
		private Producer producer;
		private List<Product> products;
		
		public ProducerTask() {
			// TODO Auto-generated constructor stub
		}
		
		public ProducerTask(Producer producer, List<Product> products) {
			this.producer = producer;
			this.products = products;
		}

		@Override
		public void run() {
			synchronized(products) {
				while (true) {
					try {
						while (products.size() >= MAX_SIZE) {
							products.wait();
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					while (products.size() < MAX_SIZE) {
						Product p = producer.produce();
						products.add(p);
						try {
							TimeUnit.SECONDS.sleep(1);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						products.notify();
					}
				}
			}
			
		}
		
	}
	
	class ConsumerTask implements Runnable {
		private List<Product> products;
		
		public ConsumerTask(List<Product> products) {
			this.products = products;
		}
		
		@Override
		public void run() {
			synchronized(products) {
				while (true) {
					try {
						while (products.size() < MAX_SIZE) {
							products.wait();
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					while (products.size() > 0) {
						Product p = products.remove(0);
						System.out.println(Thread.currentThread().getName() + " consummed a product, id = " + p.getId());
						try {
							TimeUnit.SECONDS.sleep(1);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						products.notify();
					}
				}
			}
			
		}
		
	}
	
	class Producer {
		public Product produce() {
			Product p = new Product();
			System.out.println("produced product, id = " + p.getId());
			return p;
		}
	}
	
}

多生產者多消費者

package cn.bj.demo.spring.javaevent.pc.sync;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 多個生產者,多個消費者
 * 
 * */
public class MultiProducerAndMultiConsumer {
	private static int MAX_SIZE = 10;
	private List<Product> products = null; //產品容器
	private List<ProducerTask> pTasks; //生產者任務組
	private List<ConsumerTask> cTasks; //消費者任務組
	private Object pLock; //生產者鎖
	private Object cLock; //消費者鎖
	private Producer p; //生產者
	
	public MultiProducerAndMultiConsumer() {
		p = new Producer();
		pLock = new Object();
		cLock = new Object();
		pTasks = new ArrayList<ProducerTask>();
		cTasks = new ArrayList<ConsumerTask>();
		String pName = "product thread, number";
		String cName = "consumer thread, number";
		products = new ArrayList<Product>(10);
		
		for (int i = 0; i < 10; i ++) {
			ProducerTask pTask = new ProducerTask(p, products);
			pTasks.add(pTask);
			Thread pThread = new Thread(pTask);
			pThread.setName(pName + i);
			pThread.start();
		}
		
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		for (int i = 0; i < 10; i++) {
			ConsumerTask cTask = new ConsumerTask(products);
			cTasks.add(cTask);
			Thread cThread = new Thread(cTask);
			cThread.setName(cName + i);
			cThread.start();
		}
		
		try {
			Thread.currentThread().join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("construct is over");
		
	}
	
	public static void main(String[] args) {
		
		MultiProducerAndMultiConsumer pac = new MultiProducerAndMultiConsumer();
	}
	
	
	class ProducerTask implements Runnable {
		
		private Producer producer;
		private List<Product> products;
		
		public ProducerTask() {
			// TODO Auto-generated constructor stub
		}
		
		public ProducerTask(Producer producer, List<Product> products) {
			this.producer = producer;
			this.products = products;
		}

		@Override
		public void run() {
			while (true) {
				synchronized(pLock) {
					try {
						while (products.size() == MAX_SIZE) {
							pLock.wait();
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					Product p = producer.produce();
					products.add(p);
					try {
						TimeUnit.SECONDS.sleep(1);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					if (products.size() == 3) {
						synchronized(cLock) {
							System.out.println("notify all consumer");
							cLock.notifyAll();
						}
					}
				}
			}
			
		}
		
	}
	
	class ConsumerTask implements Runnable {
		private List<Product> products;
		
		public ConsumerTask(List<Product> products) {
			this.products = products;
		}
		
		@Override
		public void run() {
			while (true) {
				synchronized(cLock) {
					try {
						while (products.size() == 0) {
							cLock.wait();
						}
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					Product p = products.remove(0);
					System.out.println("--------" + Thread.currentThread().getName() + " consummed a product, id = " + p.getId());
					try {
						TimeUnit.SECONDS.sleep(2);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					synchronized(pLock) {
						if (products.size() == 3) {
							System.out.println("notify all producer");
							pLock.notifyAll();
						}
					}
				}
			}
			
		}
		
	}
	
	class Producer {
		public Product produce() {
			Product p = new Product();
			System.out.println(Thread.currentThread().getName() + " produced product, id = " + p.getId());
			return p;
		}
	}
	
}
package cn.bj.demo.spring.javaevent.pc.sync;

public class Product {
	public static int serialNo = 0;
	
	private Integer id;
	
	protected Product(Integer id) {
		setId(id);
	}
	
	public Product() {
		this.id = serialNo ++;
	}
	
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		if (id.intValue() < 0) {
			throw new RuntimeException(id + "can not be negative");
		}
		this.id = id;
	}

	
}

上邊多生產者多消費者代碼裏因ProducerTask和ConsumerTask中獲取鎖的順序不同,會導致死鎖。暫時不處理。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章