正在運行的程序稱做一個進程,一個進程能夠包含多個線程,這些線程能夠共享進程的資源,它們共用一塊存儲空間。那麼,各個線程在訪問同一個數據對象的同時,可能引發衝突,以生產者、消費者爲例,就會出現隊列中沒有產品的狀況下,消費者扔到隊列中去拿產品,與現實世界中邏輯不相符合。使用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(); } }
producer線程向queue中放入數據,並掉調用queue.notifyAll()來喚醒全部阻塞的線程,consumer線程從queue中取數據,當沒有數據時該線程就會進入阻塞狀態,等待唄喚醒。spa