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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

在JDK1.5之前,解决生产者和消费者问题,
用的是synchronized同步+while+notify();
但是这种方法很不安全,很容易让线程全部陷入无限等待状态。
于是我们改用notiyfyAll();来解决。

这样虽然解决了安全问题,但还是存在不足和安全隐患。
notifyAll方法唤醒了线程池中全部的线程,
这并不是我们想要的!
而且,同步套同步很容易发生死锁!

在JDK1.5中提供了显示的锁机制,完美的解决了上述问题。
它既可以做到只唤醒对方线程,而不唤醒己方线程,
又能够让一个锁绑定多个对象!

下面我们首先来看看JDK1.5新特性吧!
还是用2个生产者线程和2个消费者线程来展示。
  1. import java.util.concurrent.locks.*;
  2. //一、定义资源类
  3. class Resource
  4. {
  5.         private String name;//商品名称
  6.         private int count = 1;//商品编号
  7.         private boolean flag = false;//资源监视器
  8.         private Lock lock = new ReentrantLock();//建立一个锁对象,注意这里只有一把锁。注意,Lock是接口,不可以直接创建对象
  9.         private Condition condition_Pro = lock.newCondition();//建立与lock实例一起使用的Condition实例,生产者使用
  10.         private Condition condition_Con = lock.newCondition();//建立与lock实例一起使用的Condition实例,消费者使用

  11.         //设置商品名称,商品编号自增,并打印设置结果
  12.         public void set(String name)throws InterruptedException
  13.         {
  14.                 lock.lock();//生产者线程获取锁。替换原来的synchronized
  15.                 try
  16.                 {
  17.                         while(flag)//当资源监视器为true时,生产者线程等待
  18.                                 condition_Pro.await();//生产者线程等待,并throws InterruptedException
  19.                         this.name = name;//获取商品名称
  20.                         System.out.println(Thread.currentThread().getName()+"是生产者线程,生产的商品名称为:"+name+"商品编号为:"+count);
  21.                         count++;//商品编号自增
  22.                         flag = true;//把资源监视器改为true
  23.                         condition_Con.signal();//只唤醒消费者线程
  24.                 }
  25.                 finally
  26.                 {       
  27.                         lock.unlock();//一定要释放锁
  28.                 }
  29.                        
  30.         }

  31.         //取出商品,并展示所取出的商品编号
  32.         public void get()throws InterruptedException
  33.         {
  34.                 lock.lock();//消费者线程获取锁
  35.                 try
  36.                 {
  37.                         while(!flag)//如果资源监视器为false,消费者线程等待,并抛出InterruptedException
  38.                                 condition_Con.await();
  39.                         System.out.println(Thread.currentThread().getName()+"是消费者线程,消费的商品名称为:"+name+"商品编号为:......."+count);
  40.                         flag = false;//把资源监视器改为false
  41.                         condition_Pro.signal();//只唤醒生产者线程
  42.                 }
  43.                 finally
  44.                 {
  45.                         lock.unlock();//一定要释放锁
  46.                 }       
  47.         }
  48. }

  49. //二、定义生产者类
  50. class Producer implements Runnable
  51. {
  52.         private Resource r;//引用Resource类型变量r

  53.         //重载构造函数,避免建立多个对象
  54.         Producer(Resource r)
  55.         {
  56.                 this.r = r;
  57.         }

  58.         //覆盖run方法
  59.         public void run()
  60.         {
  61.                 try
  62.                 {
  63.                         while(true)//让生产者一直在生产
  64.                         r.set("商品");
  65.                 }
  66.                 catch (InterruptedException e)
  67.                 {
  68.                         //暂不处理,以利于观察结果
  69.                 }
  70.                
  71.                
  72.         }

  73. }

  74. //三、定义消费者类
  75. class Consumer implements Runnable
  76. {
  77.         private Resource r;//引用Resource类型变量r

  78.         //重载构造函数,和生产者线程使用同一资源对象
  79.         Consumer(Resource r)
  80.         {
  81.                 this.r =r;
  82.         }

  83.         //覆盖run方法
  84.         public void run()
  85.         {
  86.                 try
  87.                 {
  88.                                         while(true)//让消费者一直取商品
  89.                         r.get();
  90.                 }
  91.                 catch (InterruptedException e)
  92.                 {
  93.                         //暂不处理,方便观察
  94.                 }
  95.         }
  96. }

  97. //四、定义测试类
  98. class MyProducerConsumerDemo2
  99. {
  100.         public static void main(String[] args)
  101.         {
  102.                 Resource r = new Resource();//建立资源
  103.                 Producer p = new Producer(r);//建立生产者
  104.                 Consumer c= new Consumer(r);//建立消费者
  105.                 Thread tp1 = new Thread(p);//建立生产者线程1
  106.                 Thread tp2 = new Thread(p);//建立生产者线程2
  107.                 Thread tp3 = new Thread(p);//建立生产者线程3
  108.                 Thread tc1 = new Thread(c);//建立消费者线程1
  109.                 Thread tc2 = new Thread(c);//建立消费者线程2
  110.                 Thread tc3 = new Thread(c);//建立消费者线程3
  111.                 tp1.start();//启动生产者线程1
  112.                 tp2.start();//启动生产者线程2
  113.                 tp3.start();//启动生产者线程3
  114.                 tc1.start();//启动消费者线程1
  115.                 tc2.start();//启动消费者线程2
  116.                 tc3.start();//启动生产者线程3
  117.         }
  118. }
复制代码




1 个回复

倒序浏览
发帖都是0回复啊,囧!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马