黑马程序员技术交流社区

标题: 关于JDK1.5新特性中的等待唤醒机制问题 [打印本页]

作者: 李斌    时间: 2012-5-24 10:53
标题: 关于JDK1.5新特性中的等待唤醒机制问题
如题
问题:在多个线程的情况,被Signal唤醒的线程 是不是也是按照线程池里面的等待顺序 进行的啊

假如在 condition_pro.signal()之前,有两个生产者处于等待状态,那么该句唤醒的是哪一个生产者线程呢?

是不是和同步Synchronized一样按照在线程池中等待的顺序进行唤醒的呢?




作者: 黑马-唐磊    时间: 2012-5-24 11:06
本帖最后由 麦田里的守望者 于 2012-5-24 12:29 编辑

有两个线程都在同时等待有可能会临时阻塞。你那个就可以自定义唤醒,我就定义两个对象来说明下,生产者和消费者。就是在一个Lock锁上绑定多个监视器对象,一个负责生产一个负责消费,可以让生产者的线程去唤醒消费者监视器上的线程,让消费者的线程去唤醒生产者监视器上的线程,代码如下:
import java.util.concurrent.locks.*;
class Resource
{
private String name;
private int count;
private boolean flag;
//创建一个锁对象。
private Lock lock = new ReentrantLock();//
//创建一个和该锁对象关联的监视器方法所属的Condition对象。
//在一个锁上提供两个监视器对象。一个负责生产者,一个负责消费。
private Condition proCon = lock.newCondition();
private Condition cusCon = lock.newCondition();
public  void set(String name)
{
  lock.lock();
  try
  {

   while(flag)
    try{proCon.await();}catch(Exception e){}//让生产者等待。
   this.name = name+"-----"+count;
   count++;
   System.out.println(Thread.currentThread().getName()+".....生产者....."+this.name);

   flag = true;
   cusCon.signal();//让生产者线程去唤醒消费者监视器上的线程。
  }
  finally
  {
   lock.unlock();
  }
}
public  void out()
{
  lock.lock();
  try
  {
  
   while(!flag)

    try{cusCon.await();}catch(Exception e){}
   System.out.println(Thread.currentThread().getName()+"...........消费者......"+this.name);
   flag = false;
      proCon.signal();
  }
  finally
  {
   lock.unlock();
  }
}
}

class Producter implements Runnable
{
private Resource r;
Producter(Resource r)
{
  this.r = r;
}
public void run()
{
  while(true)
  {
   r.set("产品");
  }
}
}

class Customer implements Runnable
{
private Resource r;
Customer(Resource r)
{
  this.r = r;
}
public void run()
{
  while(true)
  {
   r.out();
  }
}
}

class  ProCusDemo3
{
public static void main(String[] args)
{
  Resource r = new Resource();
  Producter pro = new Producter(r);
  Customer  cus = new Customer(r);
  //t1 t2 是生产者线程。
  Thread t1 = new Thread(pro);
  Thread t2 = new Thread(pro);
  //t3,t4是消费者线程。
  Thread t3 = new Thread(cus);
  Thread t4 = new Thread(cus);
  t1.start();
  t2.start();
  t3.start();
  t4.start();
}
}
当然我这里只是生产者生产一个消费一个,效率较低,但如果需要生产一堆,在消费一堆效率就高点,但那样的话就需要定义一个缓冲区和一个数组,将对象存入数组,定义一次生产100个。那就是你所说的有多个生产者,但这并不是多个生产者在同时等待而是存进数组的生产者对象在等待,唤醒的话也就是这个生产者对象,也就是消费者一消费完100个生产者,就唤醒生产者对象再生产100个生。其部分代码如下:
class BoundedBuffer {
   final Lock lock = new ReentrantLock();
   final Condition notFull  = lock.newCondition();
   final Condition notEmpty = lock.newCondition();
   final Object[] items = new Object[100];
   int putptr, takeptr, count;
   public void put(Object x) throws InterruptedException {
     lock.lock();
     try {
       while (count == items.length)
         notFull.await();
       items[putptr] = x; // 将具体的对象存储到数组中。putptr变量就是操作数组的指针。
       if (++putptr == items.length) putptr = 0;
       ++count;
       notEmpty.signal();
     } finally {
       lock.unlock();
     }
   }
   public Object take() throws InterruptedException {
     lock.lock();
     try {
       while (count == 0)
         notEmpty.await();
       Object x = items[takeptr]; //takeptr是取元素的指针。从数组中获取对象。
       if (++takeptr == items.length) takeptr = 0;
       --count;
       notFull.signal();
       return x;
     } finally {
       lock.unlock();
     }
   }
}






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