zoukankan      html  css  js  c++  java
  • 线程以及数据对象的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中取数据,当没有数据时该线程就会进入阻塞状态,等待呗唤醒。

  • 相关阅读:
    aaa
    记一次Vue实战总结
    Data too long for column 'xxx' at row 1MySql.Data.MySqlClient.MySqlPacket ReadPacket() 报错解决
    uni-app 监听返回按钮
    微信H5分享外部链接,缩略图不显示
    uni-app 动态控制下拉刷新
    vueX 的使用
    uni-app H5 腾讯地图无法导航
    uni-app支付功能
    hooks 与 animejs
  • 原文地址:https://www.cnblogs.com/yueliming/p/3257029.html
Copyright © 2011-2022 走看看