线程以及数据对象的wait()和notifyAll()方法

      正在运行的程序称作一个进程,一个进程可以包含多个线程,这些线程可以共享进程的资源,它们共用一块存储空间。那么,各个线程在访问同一个数据对象的同时,可能引起冲突,以生产者、消费者为例,就会出现队列中没有产品的情况下,消费者扔到队列中去拿产品,与现实世界中逻辑不相符合。使用synchronized关键字可以确保线程的安全运行。

  synchronized(obj){
.......
  obj.wait()/notifyAll();//是数据对象而不是线程调用wait和notifyAll方法
  }

  当给一个线程(比如A线程)的run方法体内加入上述代码时,说明A线程必须首先获得该数据对象的锁,才能对这个对象进行操作。A线程拿到这个obj数据对象的锁以后,在它释放以前任何其它线程都不能够操作此对象了,之所以这样,我们可以认为其它线程没有这把锁的钥匙。A线程执行obj.wait()方法后,它将释放其所占有的对象锁,A线程进入阻塞状态,同时A也就不具有了获得obj对象所的权力,这样其它线程就可以拿到这把锁了。obj.notifyAll()可以唤醒因obj对象而阻塞的所有线程,并允许它们有获得对象所的权力,obj.notify()是唤醒因obj对象而阻塞的任意一个线程。

  下面的程序模仿生产者和消费者:  

public class WaitAndNotify {
    private static List<Double> queue;
    public WaitAndNotify(){
        queue = new ArrayList<Double>();
    }
    
    public void begin(){
        Thread producer = new Thread(){
            public void run(){
                while(true){
                    synchronized(queue){
                        double time = 1.0d;
                    long startTime = System.currentTimeMillis();           
                    if(System.currentTimeMillis()-startTime>=time){
                            startTime =System.currentTimeMillis();
                        for(int i=0;i<10;i++){
                                queue.add((Math.random()*10000));
                        }
                    queue.notifyAll();
                    } 
                    }
                }
            }
        };
        producer.start();
        
        Thread consumer = new Thread(){
             public void run(){
                while(true){
                    synchronized(queue){
                        while(queue.isEmpty()){
                            System.out.println("队列的长度为:"+queue.size());
                            try {
                                queue.wait();
                            } catch (InterruptedException ex) {
                                Logger.getLogger(WaitAndNotify.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                        double result = queue.remove(0);
                        System.out.println("成功从队列中取到数据!"+result);
                    }
                }
            }
        };
        consumer.start();    
    }  
       
    public static void main(String[] args){
        WaitAndNotify obj = new WaitAndNotify();
        queue.add(0.1231d);
        obj.begin();
    }
}
View Code

  producer线程向queue中放入数据,并掉调用queue.notifyAll()来唤醒所有阻塞的线程,consumer线程从queue中取数据,当没有数据时该线程就会进入阻塞状态,等待呗唤醒。

posted @ 2013-08-14 13:49  华电岳黎明  阅读(5729)  评论(1编辑  收藏  举报