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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王冰 中级黑马   /  2012-7-5 04:46  /  1552 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 王冰 于 2012-7-5 16:58 编辑

                 毕老师在视频中是用while来判断标记的,这样不能控制次数,只能强制程序结束,我想问下有谁能用for循环这种方式重写,这样就既可以判断标记,还可以控制程序运行的次数。

2 个回复

倒序浏览
本帖最后由 feigecal 于 2012-7-5 20:06 编辑

因为每个线程的执行次数是不确定 的,面for循环一般是在明确循环次数的时候用比较合适,所以这里用while比较好了些,再说了这里的while的作用只是让线程每次都去判断一下标记,以防出现两个线程同时挂在判断标记之后,然后再执行时没有判断标记而出现安全问题。
  1. class Resource
  2. {
  3.           private String name;
  4.           private int count=1;
  5.           private boolean flag=false;
  6.           public synchronized void setName(String name)
  7.          {
  8.                         while(flag)
  9.                              try{this.wait();}catch(Exception e){}//如果这里是if的话,那么线程t1进来后判断然后执行,最后返回来再判断时flag为true,会等在这里,这里t2也进来后,也会挂在这里,然后消费者线程运行,然后再次唤醒线程t1和t2的时候,t2就不用再判断标记,所以会出安全问题所以要用while,可以使t2在执行之前再对标记进行判断
  10.                         this.name=name+"----"+count++;
  11.                         System.out.println(Thread.currentThread().getName()+"---shengchan---"+this.name);
  12.                         flag=true;
  13.                         this.notifyAll();//这里不仅唤醒了对方,也唤醒 了自己方的,自己方的也会抢夺执行权
  14.          }
  15.           public synchronized void out()
  16.           {
  17.                   while(!flag)
  18.                         try{this.wait();}catch(Exception e){}
  19.                   System.out.println(Thread.currentThread().getName()+"---xiaofei---"+this.name);
  20.                   flag=false;
  21.                   this.notifyAll();
  22.           }

  23. }
  24. class Producer implements Runnable
  25. {
  26.            private Resource rec;
  27.            Producer(Resource rec)
  28.           {
  29.                    this.rec=rec;
  30.            }
  31.            public void run()
  32.            {
  33.                     while(true)
  34.                    {
  35.                                   rec.setName("shangpin");
  36.                     }
  37.              }
  38. }
  39. class Consume implements Runnable
  40. {
  41.              private Resource rec;
  42.              Consume(Resource rec)
  43.             {
  44.                      this.rec=rec;
  45.              }
  46.             public void run()
  47.            {
  48.                    while(true)
  49.                    {
  50.                            rec.out();
  51.                     }
  52.            }
  53. }
  54. class ShopDemo
  55. {
  56.            public static void main(String[] args)
  57.          {
  58.                     Resource r=new Resource();
  59.                     Producer p=new Producer(r);
  60.                     Consume c=new Consume(r);
  61.                     Thread t1=new Thread(p);
  62.                     Thread t2=new Thread(p);
  63.                     Thread t3=new Thread(c);
  64.                     Thread t4=new Thread(c);
  65.                     t1.start();
  66.                     t2.start();
  67.                     t3.start();
  68.                     t4.start();
  69.          }
  70. }
复制代码
可以把它改成下面的更方便,其中 Condition将Object监视器方法wait   notify  和notifyAll分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为每个对象提供多个等待,其中,Lock 替代了synchronized方法和语句的使用,Condition 替代了 Object 监视器方法的使用。
  1. import java.util.concurrent.locks.*;
  2. class Resource
  3. {
  4.              private String name;
  5.              private int count = 1;
  6.              private boolean flag = false;
  7.              private Lock lock=new ReentrantLock();//创建一个显式的锁,替代了synchronized
  8.             Condition condition_pro=lock.newCondition();//Condition 替代了 Object 监视器方法的使用,因为Condition是一个接口,所以要用Lock的newCondition方法来返回一个特定锁的实例,来完成对不同对象提供等待和唤醒
  9.             Condition condition_con=lock.newCondition();
  10.              public void set(String name)throws InterruptedException
  11.            {
  12.                      lock.lock();
  13.                      try
  14.                      {
  15.                                 while(flag)
  16.                                       condition_pro.await();
  17.                                 this.name = name+"--"+count++;
  18.                                 System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
  19.                                 flag = true;
  20.                                  condition_con.signal();//只唤醒消费者线程
  21.                     }

  22.                      finally
  23.                       {
  24.                                 lock.unlock();//无论判断标记结果如何,或者抛出异常,最后都要释放资源解锁
  25.                      }
  26.              public void out()throws InterruptedException
  27.            {
  28.                        try
  29.                         {
  30.                                   while(!flag)
  31.                                           condition_con.await();
  32.                                   System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
  33.                                    flag = false;
  34.                                    condition_pro.signal();
  35.                           }
  36.                          finally
  37.                          {
  38.                                      lock.unlock();
  39.                           }

  40.             }
  41. }

  42. class Producer implements Runnable
  43. {
  44.             private Resource res;

  45.              Producer(Resource res)
  46.             {
  47.                        this.res = res;
  48.              }
  49.             public void run()
  50.            {
  51.                      while(true)
  52.                     {
  53.                             try
  54.                            {
  55.                                       res.set("+商品+");
  56.                             }
  57.                           catch (InterruptedException e)
  58.                         {
  59.                           }
  60.                  }

  61.            }
  62. }

  63. class Consumer implements Runnable
  64. {
  65.               private Resource res;

  66.              Consumer(Resource res)
  67.             {
  68.                           this.res = res;
  69.             }
  70.             public void run()
  71.            {
  72.                      while(true)
  73.                    {
  74.                                   try
  75.                                 {
  76.                                             res.out();
  77.                                 }
  78.                                catch (InterruptedException e)
  79.                                {
  80.                                  }
  81.                   }

  82.           }
  83. }
  84. class ProducerConsumerDemo
  85. {
  86.              public static void main(String[] args)
  87.               {
  88.                        Resource r = new Resource();

  89.                        Producer pro = new Producer(r);
  90.                         Consumer con = new Consumer(r);

  91.                          Thread t1 = new Thread(pro);//创建两个生产者线程和两个消费都线程
  92.                          Thread t2 = new Thread(pro);
  93.                          Thread t3 = new Thread(con);
  94.                          Thread t4 = new Thread(con);

  95.                          t1.start();
  96.                          t2.start();
  97.                          t3.start();
  98.                          t4.start();

  99.               }
  100. }
复制代码

点评

这位同学能不能将代码缩进写好,这样才方便其他同学阅读你的代码。  发表于 2012-7-5 18:00
回复 使用道具 举报
feigecal 发表于 2012-7-5 08:06
因为每个线程的执行次数是不确定 的,面for循环一般是在明确循环次数的时候用比较合适,所以这里用while比 ...

不好意思啊,格式改好了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马