线程以及数据对象的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对象而阻塞的任意一个线程。dom

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

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中取数据,当没有数据时该线程就会进入阻塞状态,等待呗唤醒。spa

相关文章
相关标签/搜索