黑马程序员技术交流社区

标题: 多线程中生产者和消费者的问题 [打印本页]

作者: 李贺晓    时间: 2012-10-22 22:07
标题: 多线程中生产者和消费者的问题
class ProducerConsumerDemo
{
        public static void main(String[] args)
        {
                Resourse re=new Resourse();
                Producer po=new Producer(re);
                Consumer co=new Consumer(re);
                Thread t1=new Thread(po);
                Thread t2=new Thread(po);
                Thread t3=new Thread(co);
                Thread t4=new Thread(co);
                t1.start();
                t2.start();
                t3.start();
                t4.start();
        }
}
class Resourse
{
        private String name;
        private int count=1;
        private boolean flag=false;
        public synchronized void set(String name)
        {
                if(flag)
                        try
                        {
                                wait();
                        }
                        catch (Exception e)
                        {
                        }
                this.name=name+"....."+count++;
                System.out.println(Thread.currentThread().getName()+"....生产者.."+this.name);
                flag=true;
                this.notify();

        }
        public synchronized void out()
        {
                if(!flag)
                        try
                        {
                                wait();
                        }
                        catch (Exception e)
                        {
                        }
                        System.out.println(Thread.currentThread().getName()+".........消费商品......"+this.name);
                        flag=false;
                        this.notify();
        }
}
class Producer implements Runnable
{
        private Resourse re;
        Proudcer(Resourse re)
        {
                this.re=re;
        }
        public void run()
        {
                System.out.println(re.set("++商品++"));
        }
}
class Consumer implements Runnable
{
        private Resourse re;
        Consumer(Resourse re)
        {
                this.re=re;
        }
        public void run()
        {
                System.out.println(re.out());
        }
}
当t1运行过后,把flag置为true;然后t1放弃资格,t2判断flag不为false,也放弃资格,当t3运行过之后,flag置为false,t3放弃资格,这个时候t1获取资格,然后t1判断flag为false,执行完成后,这个时候t2获取资格,毕老师在视频中讲的是,这个时候t2不在判断flag,而是直接执行try下面的代码,这是为什么,这个时候不是应该先判断flag是否为false呢???
作者: 李铁    时间: 2012-10-23 00:13
因为用的不是while(flag),不是while(){}结构,所以不会循环。
带你走一遍思路,你就明白了!
开始t1执行后,生产一个商品,flag为true,1放弃资格,t2判断flag为true,t2放弃资格。t3开始执行,判断flag为true,消费一个商品,flag为false, t4判断flag为false, t4放弃资格
当t1获得执行权后,执行完后flag为true,生产一个商品,唤醒了t2 。t1放弃资格,t2就直接往下执行了,然后又输出一个“生产者”,所以出现了生产两个商品的情况。
解决的方法就是将if改为while结构后,t2就不会再生产了,直接放弃资格,最后导致全部等待,所以要把this.notify()改为this.notifyAll()就可以解决了。
作者: 李贺晓    时间: 2012-10-23 08:44
李铁 发表于 2012-10-23 00:13
因为用的不是while(flag),不是while(){}结构,所以不会循环。
带你走一遍思路,你就明白了!
开始t1执行后 ...

t2第一次放弃资格的时候,下一次唤醒t2的时候,t2不是还应该重新判断flag,此时的flag还是为true,这个时候t2不是还是应该放弃资格呢,怎么会顺序往下执行呢
作者: 灵感    时间: 2012-10-23 11:26
本帖最后由 严学韦 于 2012-10-23 12:58 编辑

if(flag)
         try
         {
                 wait();
         }
         catch (Exception e)
         {
         }
哥们,是这样子的,毕老师不是每次都用while(true)让程序执行多次吗?
他为什么不用if(true)让代码执行多次呢?你应该知道原因了吧?
while执行多次,if执行单次
线程2是走了if之后放弃资格的
所以当线程2从放弃资格到获取到资格时它就不再判断flag了,直接往下走了
如果将if改成while的话线程2必须再次判断flag




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2