Java多執行緒與併發程式設計總結(一)
Java併發程式設計:執行緒間協作的兩種方式:wait、notify、notifyAll和Condition
在前面我們將了很多關於同步的問題,然而在現實中,需要執行緒之間的協作。比如說最經典的生產者-消費者模型:當佇列滿時,生產者需要等待佇列有空間才能繼續往裡面放入商品,而在等待的期間內,生產者必須釋放對臨界資源(即佇列)的佔用權。因為生產者如果不釋放對臨界資源的佔用權,那麼消費者就無法消費佇列中的商品,就不會讓佇列有空間,那麼生產者就會一直無限等待下去。因此,一般情況下,當佇列滿時,會讓生產者交出對臨界資源的佔用權,並進入掛起狀態。然後等待消費者消費了商品,然後消費者通知生產者佇列有空間了。同樣地,當佇列空時,消費者也必須等待,等待生產者通知它佇列中有商品了。這種互相通訊的過程就是執行緒間的協作。
今天我們就來探討一下Java中執行緒協作的最常見的兩種方式:利用Object.wait()、Object.notify()和使用Condition
以下是本文目錄大綱:
一.wait()、notify()和notifyAll()
二.Condition
三.生產者-消費者模型的實現
若有不正之處請多多諒解,並歡迎批評指正。
請尊重作者勞動成果,轉載請標明原文連結:
http://www.cnblogs.com/dolphin0520/p/3920385.html
1)wait()、notify()和notifyAll()方法是本地方法,並且為final方法,無法被重寫。
2)呼叫某個物件的wait()方法能讓當前執行緒阻塞,並且當前執行緒必須擁有此物件的monitor(即鎖)
3)呼叫某個物件的notify()方法能夠喚醒一個正在等待這個物件的monitor的執行緒,如果有多個執行緒都在等待這個物件的monitor,則只能喚醒其中一個執行緒;
4)呼叫notifyAll()方法能夠喚醒所有正在等待這個物件的monitor的執行緒;
生產者-消費者模型的實現
public class Test {
private int queueSize = 10;
private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
public static void main(String[] args) {
Test test = new Test();
Producer producer = test.new Producer();
Consumer consumer = test.new Consumer();
producer.start();
consumer.start();
}
class Consumer extends Thread{
@Override
public void run() {
consume();
}
private void consume() {
while(true){
synchronized (queue) {
while(queue.size() == 0){
try {
System.out.println("佇列空,等待資料");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
queue.notify();
}
}
queue.poll(); //每次移走隊首元素
queue.notify();
System.out.println("從佇列取走一個元素,佇列剩餘"+queue.size()+"個元素");
}
}
}
}
class Producer extends Thread{
@Override
public void run() {
produce();
}
private void produce() {
while(true){
synchronized (queue) {
while(queue.size() == queueSize){
try {
System.out.println("佇列滿,等待有空餘空間");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
queue.notify();
}
}
queue.offer(1); //每次插入一個元素
queue.notify();
System.out.println("向佇列取中插入一個元素,佇列剩餘空間:"+(queueSize-queue.size()));
}
}
}
}
}
Condition是在java 1.5中才出現的,它用來替代傳統的Object的wait()、notify()實現執行緒間的協作,相比使用Object的wait()、notify(),使用Condition1的await()、signal()這種方式實現執行緒間協作更加安全和高效。因此通常來說比較推薦使用Condition,在阻塞佇列那一篇博文中就講述到了,阻塞佇列實際上是使用了Condition來模擬執行緒間協作。
- Condition是個介面,基本的方法就是await()和signal()方法;
- Condition依賴於Lock介面,生成一個Condition的基本程式碼是lock.newCondition()
- 呼叫Condition的await()和signal()方法,都必須在lock保護之內,就是說必須在lock.lock()和lock.unlock之間才可以使用
Conditon中的await()對應Object的wait();
Condition中的signal()對應Object的notify();
Condition中的signalAll()對應Object的notifyAll()。
使用Condition實現
public class Test {
private int queueSize = 10;
private PriorityQueue<Integer> queue = new PriorityQueue<Integer>(queueSize);
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public static void main(String[] args) {
Test test = new Test();
Producer producer = test.new Producer();
Consumer consumer = test.new Consumer();
producer.start();
consumer.start();
}
class Consumer extends Thread{
@Override
public void run() {
consume();
}
private void consume() {
while(true){
lock.lock();
try {
while(queue.size() == 0){
try {
System.out.println("佇列空,等待資料");
notEmpty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.poll(); //每次移走隊首元素
notFull.signal();
System.out.println("從佇列取走一個元素,佇列剩餘"+queue.size()+"個元素");
} finally{
lock.unlock();
}
}
}
}
class Producer extends Thread{
@Override
public void run() {
produce();
}
private void produce() {
while(true){
lock.lock();
try {
while(queue.size() == queueSize){
try {
System.out.println("佇列滿,等待有空餘空間");
notFull.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.offer(1); //每次插入一個元素
notEmpty.signal();
System.out.println("向佇列取中插入一個元素,佇列剩餘空間:"+(queueSize-queue.size()));
} finally{
lock.unlock();
}
}
}
}
}
相關文章
- 程式設計體系結構(05):Java多執行緒併發程式設計Java執行緒
- Java併發程式設計:Java執行緒Java程式設計執行緒
- 多執行緒程式設計總結:一、認識多執行緒本質執行緒程式設計
- iOS多執行緒程式設計:執行緒同步總結iOS執行緒程式設計
- Java高併發與多執行緒(一)-----概念Java執行緒
- Swift多執行緒程式設計總結Swift執行緒程式設計
- java併發程式設計——執行緒池Java程式設計執行緒
- java併發程式設計——執行緒同步Java程式設計執行緒
- Java 面試必會知識點:Java 多執行緒與併發程式設計Java面試執行緒程式設計
- Java 多執行緒 | 併發知識問答總結Java執行緒
- 併發程式設計與執行緒安全程式設計執行緒
- 多執行緒併發程式設計“鎖”事執行緒程式設計
- JAVA 多執行緒總結(一)Java執行緒
- java多執行緒與併發 - 併發工具類Java執行緒
- Java 併發和多執行緒(一) Java併發性和多執行緒介紹[轉]Java執行緒
- 好程式設計師Java培訓分享Java多執行緒併發程式設計師Java執行緒
- Java 多執行緒與併發程式設計 · Java 工程師必知必會Java執行緒程式設計工程師
- java多執行緒與併發 - 執行緒池詳解Java執行緒
- 多執行緒程式設計,處理多執行緒的併發問題(執行緒池)執行緒程式設計
- iOS多執行緒程式設計總結(上)iOS執行緒程式設計
- iOS多執行緒程式設計總結(中)iOS執行緒程式設計
- iOS多執行緒程式設計總結(下)iOS執行緒程式設計
- C++ 多執行緒程式設計總結C++執行緒程式設計
- 多執行緒與高併發(一)多執行緒入門執行緒
- java併發程式設計 | 執行緒詳解Java程式設計執行緒
- Java併發程式設計-執行緒基礎Java程式設計執行緒
- iOS多執行緒程式設計——GCD與NSOperation總結iOS執行緒程式設計GC
- Java執行緒與併發程式設計實踐----額外的執行緒能力Java執行緒程式設計
- Java 多執行緒併發程式設計之 Synchronized 關鍵字Java執行緒程式設計synchronized
- JAVA多執行緒併發Java執行緒
- Java併發(一)----程式、執行緒、並行、併發Java執行緒並行
- iOS多執行緒之併發程式設計-4iOS執行緒程式設計
- Java併發程式設計之執行緒安全、執行緒通訊Java程式設計執行緒
- 執行緒併發總結執行緒
- java多執行緒總結(系列一)Java執行緒
- Java併發程式設計之執行緒篇之執行緒的由來(一)Java程式設計執行緒
- 程式設計思想之多執行緒與多程式(3):Java 中的多執行緒程式設計執行緒Java
- Java中的多執行緒程式設計(超詳細總結)Java執行緒程式設計