A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 善良的禽兽 中级黑马   /  2015-9-24 21:26  /  571 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文


/*
* 需求, 写一个程序来解决生产消费者问题(多线程);
*
* 首先定义一个类Resoucer来描述商品;
*     这个Resoucer类应该有一个int类型的成员变量用来修饰当前商品的编号;
*     还应该有一个String类型的变量name用来记录当前商品名称;
*     此外还应该有一个boolean类型的变量用来标记当前是否有商品被生产或者消费;
* 然后定义一个类Producer来实现Runnable的run方法;
* 再定义一个类Consumer来实现Runnable中的run方法;
*
*
* 总算搞懂了这里为什么编译运行, 运行到一半会卡住不动了:
*
* 我们这里总共有五条线程
* main线程......也就是主函数线程;
* Thread0 和 Thread1  这两条线程是生产者线程
* Thread2 和 Thread3  这两条线程是消费者线程
*
* 首先Thread0生产一个商品, 然后flag被赋值为true, 并进入了线程池中,
* 此时Thread1线程开启, 因为flag为true,Thread1也进入了线程池,
*
* Thread2线程开启, 消费了Thread0生产的商品后, 将flag赋值为false, 并进入线程池,
* Thread3经过判断之后同样进入线程池...
*
* 到目前为止线程池中的线程队列为:
*
* Thread0,   Thread1,   Thread2,  Thread3;
*
* 当然最先唤醒的是Thread0,此时flag的值为false, Thread0便跳出while循环;
* 生产完商品之后, 将flag赋值为true, 并将线程池中的第一个线程唤醒(也就是Thread1, Thread1仅仅是获取资格, 并没有执行权)
* 然后Thread0在执行flag==true判断的时候, 又被扔进了线程池, 此时把控制权交给了Thread1, 很不幸, 此时Thread1这条线程,
* 执行阶段正好在while(flag == true)这个循环中, 更不幸的是, flag正好为true;  此时就是一个死循环了, 而且Thread1这条线程
* 也没法notify Thread2或者Thread3来消费商品, 于是, 大家都睡了.....
*
*
*
* 总结:   当然, 不同的机器不同的状态下, 所执行的线程顺序可能不一样,
* 但是都有可能遇到这种全部等待的情况,
* 造成这种情况的原因就是某一线程又唤醒了本类线程,
* 而且本类线程不满足条件,导致刚唤醒的线程又直接wait()了,
* 没法唤醒对方线程,所以程序就卡住不动了, 这应该不叫死锁, 而是全部等待....  
*/

class Resoucer
{
    private String name;
    private int cnt = 1;
    private boolean flag = false;

    public synchronized void set(String name)
    {
        while(flag == true)
            try{this.wait();}catch(Exception e){}

        this.name = name + ".....id =" + cnt++;
        System.out.println(Thread.currentThread().getName() + this.name + "...生产者...");
        try{Thread.sleep(5);}catch(Exception e){}
        flag = true;

        this.notify();

    }

    public synchronized void out()
    {
          while(flag == false)
                try{this.wait();}catch(Exception e){}

          System.out.println(Thread.currentThread().getName() + this.name + "_______消费者______");
          try{Thread.sleep(5);}catch(Exception e){}
          flag = false;

          this.notify();
    }
}

class Producer implements Runnable
{
     Resoucer rc;

     Producer(Resoucer rc)
     {
          this.rc = rc;
     }

     public void run()
     {
         while(true)
         {
            rc.set("+++商品+++");
         }
     }
}

class Consumer implements Runnable
{
     Resoucer rc;
     Consumer(Resoucer rc)
     {
           this.rc = rc;
     }

     public void run()
     {
         while(true)
         {
              rc.out();
         }
     }
}

class demo
{
    public static void main(String[] args)
    {
         Resoucer rc = new Resoucer();

         new Thread(new Producer(rc)).start();
         new Thread(new Producer(rc)).start();

         new Thread(new Consumer(rc)).start();
         new Thread(new Consumer(rc)).start();

    }
}

1 个回复

倒序浏览
总结的很详细,支持一下
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马