線程以及數據對象的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中取數據,當沒有數據時該線程就會進入阻塞狀態,等待唄喚醒。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM