packagecom.produce;importjava.util.LinkedList;importjava.util.Queue;/*@author shijin

* 生产者与消费者模型中,要保证以下几点:

* 1 同一时间内只能有一个生产者生产 生产方法加锁sychronized

* 2 同一时间内只能有一个消费者消费 消费方法加锁sychronized

* 3 生产者生产的同时消费者不能消费 生产方法加锁sychronized

* 4 消费者消费的同时生产者不能生产 消费方法加锁sychronized

* 5 共享空间空时消费者不能继续消费 消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行

* 6 共享空间满时生产者不能继续生产 生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行*/

//主类
public classProducerConsumer
{public static voidmain(String[] args)
{
StackBasket s= newStackBasket();
Producer p= newProducer(s);
Consumer c= newConsumer(s);
Thread tp= newThread(p);
Thread tc= newThread(c);
tp.start();
tc.start();
}
}/*** 馒头
**/
classMantou
{private intid;
Mantou(intid){this.id =id;
}publicString toString(){return "馒头ID" +id;
}
}/*** 共享栈空间 仓库
**/
classStackBasket
{
Queue sm = new LinkedList();int index = 6;/*** show 生产方法.
* show 该方法为同步方法,持有方法锁;
* show 首先循环判断满否,满的话使该线程等待,释放同步方法锁,允许消费;
* show 当不满时首先唤醒正在等待的消费方法,但是也只能让其进入就绪状态,
* show 等生产结束释放同步方法锁后消费才能持有该锁进行消费
*@paramm 元素
*@return没有返回值*/
public synchronized voidpush(Mantou m){try{while(index ==sm.size()){
System.out.println("!!!!!!!!!生产满了!!!!!!!!!");this.wait();
}this.notify();
}catch(InterruptedException e){
e.printStackTrace();
}catch(IllegalMonitorStateException e){
e.printStackTrace();
}
//此处可执行逻辑操作,如从数据库取出数据
sm.offer(m);
System.out.println("生产了:" + m + " 仓库有:" + sm.size() + "个馒头");
}/*** show 消费方法
* show 该方法为同步方法,持有方法锁
* show 首先循环判断空否,空的话使该线程等待,释放同步方法锁,允许生产;
* show 当不空时首先唤醒正在等待的生产方法,但是也只能让其进入就绪状态
* show 等消费结束释放同步方法锁后生产才能持有该锁进行生产
*@paramb true 表示显示,false 表示隐藏
*@return没有返回值*/
public synchronizedMantou pop(){try{while(sm.size() == 0){
System.out.println("!!!!!!!!!消费光了!!!!!!!!!");this.wait();
}this.notify();
}catch(InterruptedException e){
e.printStackTrace();
}catch(IllegalMonitorStateException e){
e.printStackTrace();
}
Mantou mantou=sm.poll();
//此处可执行逻辑代码,如将数据更新回数据库
System.out.println("消费了:" + mantou + " 仓库有:" + sm.size() + "个馒头");returnmantou;
}
}/*** 生产者
**/
class Producer implementsRunnable
{
StackBasket ss= newStackBasket();
Producer(StackBasket ss){this.ss =ss;
}/*** show 生产进程.*/
public voidrun(){for(int i = 0;i < 20;i++){
Mantou m= newMantou(i);

ss.push(m);//System.out.println("生产了:" + m + " 共" + ss.index + "个馒头");//在上面一行进行测试是不妥的,对index的访问应该在原子操作里,因为可能在push之后此输出之前又消费了,会产生输出混乱

try{
Thread.sleep((int)(Math.random()*500));
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}/*** 消费者
**/
class Consumer implementsRunnable
{
StackBasket ss= newStackBasket();
Consumer(StackBasket ss){this.ss =ss;
}/*** show 消费进程.*/
public voidrun(){for(int i = 0;i < 20;i++){

Mantou m=ss.pop();//System.out.println("消费了:---------" + m + " 共" + ss.index + "个馒头");//同上 在上面一行进行测试也是不妥的,对index的访问应该在原子操作里,因为可能在pop之后此输出之前又生产了,会产生输出混乱

try{
Thread.sleep((int)(Math.random()*1000));
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}