java多線程的理解

sleep()是Thread類的特有方法,wait() 與 notify/notifyAll() 是Object類的方法,在執行兩個方法時,要先獲得鎖,因此wait() 與 notify/notifyAll() 一般是在臨界區內執行,就是在加了synchronized的代碼中執行

當線程執行wait()時,會把當前的鎖釋放,然後讓出CPU,進入等待狀態。

 當執行notify/notifyAll方法時不會立即釋放鎖,會喚醒一個處於等待該對象鎖的線程,然後繼續往下執行,直到執行完退出對象鎖鎖住的區域(synchronized修飾的代碼塊)後再釋放鎖。notify/notifyAll()執行後,並不立即釋放鎖,而是要等到執行完臨界區中代碼後,再釋放。在實際編程中,我們應該儘量在線程調用notify/notifyAll()後,立即退出臨界區。即不要在notify/notifyAll()後面再寫一些耗時的代碼。

 

  • Thread.sleep()讓線程從 【running】 -> 【阻塞態】 時間結束/interrupt -> 【runnable】
  • Object.wait()讓線程從 【running】 -> 【等待隊列】notify -> 【鎖池】 -> 【runnable】

 推薦的常用同步方法

(1)Object的wait() / notify()方法
(2)LockCondition的await() / signal()方法
(3)BlockingQueue阻塞隊列方法(推薦)

wait() / notify()方法-同步代碼塊

		@Override
		public void run() {
			while (true) {
				synchronized (queue) {
					while ((queue.size() == Max_Size)) {
						System.out.println(getName() + " queue is full!!");
						try {
							queue.wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					int i = new Random().nextInt(10);
					System.out.println(getName() + " put " + i + " into queue!");
					queue.add(i);
					try {
						Thread.sleep(new Random().nextInt(1000));
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					queue.notify();
				}
			}
		}

業務類內循環調度,需獲取wait()/notify()對象的鎖,方法上加鎖不行,需要對Object.wait()的Object加鎖。遇不滿足條件則進入等待。

wait() / notify()方法-同步方法

	public static class Store {
		private final int MAX_SIZE = 10;
		private int count;
		
		public synchronized void add () throws Exception{
			if (count < MAX_SIZE) {
				count++;
				System.out.println(Thread.currentThread().getName()+" put "+count);
				this.notifyAll();
			}else {
				System.out.println(Thread.currentThread().getName()+" store is full!!");
				this.wait();
			}
		}
		
		public synchronized void remove () throws Exception{
			if (count >0) {
				count--;
				System.out.println(Thread.currentThread().getName()+" remove "+count);
				this.notifyAll();
			}else {
				System.out.println(Thread.currentThread().getName()+" store is empty!!");
				this.wait();
			}
		}
		
	}
	/*
	 * @author wsg
	 * 倉庫類,提供添加和刪除接口
	 */
	public static  class Productor extends Thread{
		private Store store;

		public Store getStore() {
			return store;
		}

		public void setStore(Store store) {
			this.store = store;
		}
		
		@Override
		public void run() {
			while(true){
				try {
					store.add();
					Thread.sleep(100);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		}
	}
	

該實現方式把同步業務放在了共享存儲內,存儲應該只有增刪功能,不符合面向對象的思想。在函數上增加同步,在函數內使用this.wait(),函數上增加synchronized等於對該對象this加鎖,然後使用this.wait(),與需要對Object.wait()的Object加鎖不衝突。

具體實現可參考:https://blog.csdn.net/u010983881/article/details/78554671

參考:http://ifeve.com/thread-signaling/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章