生產者消費者是個經典的話題了,此次主要經過這個話題談談wait方法與sleep方法。java
wait方法和sleep方法都是讓出cpu佔有權,讓其它線程可以獲得運行,不一樣的地方在於wait方法能夠經過notify或者notifyAll方法主動喚醒或者wait必定的等待時間自動恢復運行,而sleep方法只能在等待必定的時間後自動恢復運行。測試
通常咱們看到的生產者消費者實現都是經過wait、notify、notifyAll或者是condition接口的await、signal、signalAll方法實現的。此次咱們想看看經過sleep方法實現與wait方法實現的效率有多大差異。this
wait方式實現:線程
package pro_con;blog
import java.util.LinkedList;接口
public class QueueWithWait<T> extends BlockingQueue<T> {
private LinkedList<T> queue = new LinkedList<>();
private final int cacheSize;隊列
public QueueWithWait(int cacheSize) {
super();
this.cacheSize = cacheSize;
}ci
public T take() {
synchronized (queue) {
while(true) {
if(queue.size()>0) {
T obj = queue.poll();
queue.notify();
return obj;
}else {
try {
queue.wait();
} catch (InterruptedException e) {
}
}
}
}
}it
public void put(T obj) {io
synchronized (queue) {
while (true) {
if (queue.size() < cacheSize) {
queue.offer(obj);
queue.notify();
break;
} else {
try {
queue.wait();
} catch (InterruptedException e) {
}
}
}
}
}
}
sleep方式實現:
package pro_con;
import java.util.LinkedList;
public class QueueWithSleep<T> extends BlockingQueue<T> {
private LinkedList<T> queue = new LinkedList<>();
private final int cacheSize;
public QueueWithSleep(int cacheSize) {
super();
this.cacheSize = cacheSize;
}
public T take() {
while (true) {
synchronized (queue) {
if (queue.size() > 0) {
T obj = queue.poll();
return obj;
} else {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
}
}
}
public void put(T obj) {
while (true) {
synchronized (queue) {
if (queue.size() < cacheSize) {
queue.offer(obj);
break;
} else {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
}
}
}
}
測試結果:
wait方式的前7次結果以下圖所示
sleep方式的前7次結果以下圖所示
結果是很明顯的,wait方式比sleep方式效率要高出不少,可能會簡單的認爲sleep的時間過長致使的,那麼把sleep方法去掉後結果以下:
結果發現效率與wait方式差很少,可是仔細觀察會發現這種去掉sleep的方法結果是不穩定的,不像wait方法穩定在290萬左右,緣由是
去掉sleep方法後同一個put或者take方法在達到臨界條件時有必定概率會屢次循環,不像wait方法主動讓出cpu佔用權,從而下降了程序
的效率。
結論:
主流的生產者消費者模式仍是用wait或者condition接口的await方式,但還有一種無鎖隊列會比這更加高效。
代碼下載連接:https://pan.baidu.com/s/1ciLBNiIc9670cwdat2qspQ 密碼:z5d1