黑马程序员技术交流社区
标题:
一段不起眼的小程序引发的暴虐
[打印本页]
作者:
边情2015
时间:
2015-10-5 10:07
标题:
一段不起眼的小程序引发的暴虐
眼看下面这段不起眼的小程序,很简单,很单纯。似曾相识,却又不太一样。吃透它,细心体会其中的每一个细节。废话不多说。上代码!
记录每一天,先来一段插曲描述一下,程序后还有分析与思考:
用四个线程实现,两个生产者生产产品后,另两个消费者消费。要求生产一个产品必须先消费才能再生产下一个商品。
分析:生产者与消费者之前有共享资源(产品);且有多个线程(两个生产者与两个消费者)参与其中;生产者生产过程和消费过程都会使用到产品。以上三点,可以判断整个过程会引发安全隐患。我只需将双方使用产品的过程进行同步实现即可解决这个问题,这个安全隐患。
来吧,程序代码如下:
class ProduceConsumerDemo
{
public static void main(String[] args)
{
Resource r = new Resource();
Thread t1 = new Thread(newProduce(r));
Thread t2 = new Thread(newConsumer(r));
Thread t3 = new Thread(newProduce(r));
Thread t4 = new Thread(newConsumer(r));
t1.start();
t2.start();
t3.start();
t4.start();
/*
new Thread(newProduce(r)).start();
new Thread(newConsumer(r)).start();
new Thread(newProduce(r)).start();
new Thread(newConsumer(r)).start();
*/
}
}
classResource
{
private String name;
private int count = 1;
private boolean flag;
//t1和t2拥有不同的锁(Produce和Consumer对像),因此能够进入set函数内
public synchronized void set(Stringname)//同步函数的锁是this,在这里this代表它所在类Resource的引用(即调用都是对象)
{
//if(flag) //换while,那么问题就来了,程序会停住。这时,唤醒方式改成notifyAll就可以解决。
//考虑如何处理?想到反复判断flag不就解决了,因此用while(flag)替换if(flag)
// t1放弃资格 t2获取资格//当t2获取资格后就不再判断flag,这样会出现还没消费掉t1生产的商品他t2就紧接着生产。
while(flag)try{this.wait();}catch(Exception e){}
this.name =name+"----"+count++;
System.out.println(Thread.currentThread().getName()+"--生产者--"+this.name);
flag = true;
//this.notify();//notify唤醒的是池中的第一个等待中的线程 notifyAll唤醒池中所有等待中的进程
this.notifyAll();
}
//t1和t2拥有不同的锁(Produce和Consumer对像),因此能够进入out函数内
public synchronized void out()//同步函数的锁是this,在这里this代表它所在类Resource的引用(即调用都是对象)
{
/*if(!flag)*/
//// t1放弃资格 t2获取资格
while(!flag) try{this.wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"--消费者--------"+name);
flag = false;
//this.notify();
this.notifyAll();
}
}
classProduce implements Runnable
{
Resource r = new Resource();
Produce(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.set("商品");
}
}
}
classConsumer implements Runnable
{
Resource r = new Resource();
Consumer(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
复制代码
为实现同步,加入同步函数后发现。程序并达到没有预期的要求(产品必须先消费才能再生产下一个商品)。为达到这个目的,首先分析问题所在。经验证发现在使用产品过程中,同步函数监视器(锁)只能监视共同使用一个监视器的进程才有效,即无法监视具有不同监视器的对象。所以会导致程序中t1和t2对象判断语句判断后停留在那里,这样还会带来安全隐患。因此,为了达到多次判断,我们选择使用while循环语句。当然,引入while循环语句会带来程序停留的问题,不过使用Objec中的唤醒机制中的notifyAll完美解决了这个问。其中,一定要注意使用notify唤醒为什么会程序停留,因为其唤醒的只是池中的第一个进程。这样不难分析,其中生产者与消费者会多次使用产品的问题,而不是目标所要求的。
小小总结:要是有时间用思维导图体现,那就很Nice了。每天只24个小时,加油!
作者:
Synaric
时间:
2015-10-5 11:02
不错的例子
作者:
冰霜之卅
时间:
2015-10-5 13:19
排版太差 不容易看懂。
作者:
往事如风555
时间:
2015-10-5 16:06
谢谢分享!
作者:
blensmile
时间:
2015-10-5 18:36
谢谢分享~思维导图推荐imindmap~
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2