您的位置:首页 > 职场人生

黑马程序员--生产者和消费者模式

2015-06-06 13:09 405 查看
------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

在学习了毕老师的生产者消费者模式,下面写下关于生产者消费者模式的理解,生产者生产产品到资源类中,而消费者冲资源类中取出产品并消费,如果只开启一个生产者的线程,一个消费者的线程,不会出问题如果开启两个生产者,两个消费者就会出现问题代码如下面所示:

class ProducerConsumerDemo 

{
public static void main(String[] args) 
{
Resource r = new Resource();

Producer pro = new Producer(r);
Consumer con = new Consumer(r);

Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);

t1.start();
t2.start();
t3.start();
t4.start();

}

}

class Resource

{
private String name;
private int count = 1;
private boolean flag = false;
//  t1    t2
public synchronized void set(String name)
{
if(flag)
try{this.wait();}catch(Exception e){}//t1(放弃资格)  t2(获取资格)
this.name = name+"--"+count++;

System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
this.notify();
}

//  t3   t4  
public synchronized void out()
{
if(!flag)
try{wait();}catch(Exception e){}//t3(放弃资格) t4(放弃资格)
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
this.notify();
}

}

class Producer implements Runnable

{
private Resource res;

Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
res.set("+商品+");
}
}

}

class Consumer implements Runnable

{
private Resource res;

Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
res.out();
}
}

}

代码如上所示,这样如果启用四个线程,如果线程t1进来发现 flag为false,那么他就进行生产,而生产完后,将flag设置成true;通知t2, t2线程进来后发现flag为true,就进入挂起状态,t3进入后,发现flag为true 就进行消费,然后将flag变成false ,这样t4线程进来就会挂起,这样四个线程就全部挂起,程序停止,要解决这个问题就要将notify()改为notifyAll(),notifyAll()是通知全部线程,notify()只通知程序内线程,改为notifyAll()还是会出问题。假如改成notifyAll()
t1,进入发现flag为false 进进行生产,生产完,把flag变成了true,通知其他线程,假如t2进入 ,发现flag为true ,就会挂起,这时候t3进入,发现flag为true,就进行消费产品,然后将flag变成flag,这时候通知别的线程访问,这时候t2如果被唤起,则不会重新进行判断,就进行生产,造成t1制作的产品没法被消费,解决这个问题的方法是将if(flag)变成while(flag)这样,while循环在每次执行的 时候都会进行判断,就会消除了这种情况。

改正后的代码如下

class ProducerConsumerDemo 

{
public static void main(String[] args) 
{
Resource r = new Resource();

Producer pro = new Producer(r);
Consumer con = new Consumer(r);

Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con);

t1.start();
t2.start();
t3.start();
t4.start();

}

}

/*

对于多个生产者和消费者。

为什么要定义while判断标记。

原因:让被唤醒的线程再一次判断标记。

为什么定义notifyAll,

因为需要唤醒对方线程。

因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

*/

class Resource

{
private String name;
private int count = 1;
private boolean flag = false;
//  t1    t2
public synchronized void set(String name)
{
while(flag)
try{this.wait();}catch(Exception e){}//t1(放弃资格)  t2(获取资格)
this.name = name+"--"+count++;

System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
this.notifyAll();
}

//  t3   t4  
public synchronized void out()
{
while(!flag)
try{wait();}catch(Exception e){}//t3(放弃资格) t4(放弃资格)
System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
flag = false;
this.notifyAll();
}

}

class Producer implements Runnable

{
private Resource res;

Producer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
res.set("+商品+");
}
}

}

class Consumer implements Runnable

{
private Resource res;

Consumer(Resource res)
{
this.res = res;
}
public void run()
{
while(true)
{
res.out();
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  黑马程序员 java