線程以及數據對象的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

相關文章
相關標籤/搜索