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)Lock和Condition的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