好程式設計師分享同一資源多執行緒併發訪問時的完整性
好程式設計師面試題分享 同一資源多執行緒併發訪問時的完整性 , 常用的同步方法是採用訊號或加鎖機制,確保資源在任意時刻至多被一個執行緒訪問。Java 語言在多執行緒程式設計上實現了完全物件化,提供了對同步機制的良好支援。
在Java 中一共有四種方法支援同步,其中前三個是同步方法,一個是管道方法。管道方法不建議使用,阻塞佇列方法在問題 4 已有描述,現只提供前兩種實現方法。
- wait()/notify() 方法
- await()/signal() 方法
- BlockingQueue 阻塞佇列方法
- PipedInputStream/PipedOutputStream
一、生產者類:
```
public class Producer extends Thread { // 每次生產的產品數量
private int num;
// 所在放置的倉庫
private Storage storage;
// 建構函式,設定倉庫
public Producer(Storage storage) {
this.storage = storage;
}
// 執行緒 run 函式
public void run() {
produce(num);
}
// 呼叫倉庫 Storage 的生產函式
public void produce(int num) {
storage.produce(num);
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Storage getStorage() {
return storage;
}
public void setStorage(Storage storage) {
this.storage = storage;
}
}
```
二、消費者類:
```
public class Consumer extends Thread { // 每次消費的產品數量
private int num;
// 所在放置的倉庫
private Storage storage;
// 建構函式,設定倉庫
public Consumer(Storage storage) {
this.storage = storage;
}
// 執行緒 run 函式
public void run() {
consume(num);
}
// 呼叫倉庫 Storage 的生產函式
public void consume(int num) {
storage.consume(num);
}
// get/set 方法
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Storage getStorage() {
return storage;
}
public void setStorage(Storage storage) {
this.storage = storage;
}
}
```
倉庫類:(wait()/notify() 方法 )
```
public class Storage { // 倉庫最大儲存量
private final int MAX_SIZE = 100;
// 倉庫儲存的載體
private LinkedList list = new LinkedList();
// 生產 num 個產品
public void produce(int num) {
// 同步程式碼段
synchronized (list) {
// 如果倉庫剩餘容量不足
while (list.size() + num > MAX_SIZE) {
System.out.print(" 【要生產的產品數量】 :" + num);
System.out.println(" 【庫存量】 :" + list.size() + " 暫時不能執行生產任務 !");
try {
list.wait();// 由於條件不滿足,生產阻塞
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 生產條件滿足情況下,生產 num 個產品
for (int i = 1; i <= num; ++i) {
list.add(new Object());
}
System.out.print(" 【已經生產產品數】 :" + num);
System.out.println(" 【現倉儲量為】 :" + list.size());
list.notifyAll();
}
}
// 消費 num 個產品
public void consume(int num) {
// 同步程式碼段
synchronized (list) {
// 如果倉庫儲存量不足
while (list.size() < num) {
System.out.print(" 【要消費的產品數量】 :" + num);
System.out.println(" 【庫存量】 :" + list.size() + " 暫時不能執行生產任務 !");
try {
// 由於條件不滿足,消費阻塞
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 消費條件滿足情況下,消費 num 個產品
for (int i = 1; i <= num; ++i) {
list.remove();
}
System.out.print(" 【已經消費產品數】 :" + num);
System.out.println(" 【現倉儲 ) 量為】 :" + list.size());
list.notifyAll();
}
}
// get/set 方法
public LinkedList getList() {
return list;
}
public void setList(LinkedList list) {
this.list = list;
}
public int getMAX_SIZE() {
return MAX_SIZE;
}
}
```
倉庫類:(await()/signal() 方法 )
```
public class Storage { // 倉庫最大儲存量
// 倉庫最大儲存量
private final int MAX_SIZE = 100;
// 倉庫儲存的載體
private LinkedList list = new LinkedList();
// 鎖
private final Lock lock = new ReentrantLock();
// 倉庫滿的條件變數
private final Condition full = lock.newCondition();
// 倉庫空的條件變數
private final Condition empty = lock.newCondition();
// 生產 num 個產品
public void produce(int num) {
// 獲得鎖
lock.lock();
// 如果倉庫剩餘容量不足
while (list.size() + num > MAX_SIZE) {
System.out.print(" 【要生產的產品數量】 :" + num);
System.out.println(" 【庫存量】 :" + list.size() + " 暫時不能執行生產任務 !");
try {
// 由於條件不滿足,生產阻塞
full.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 生產條件滿足情況下,生產 num 個產品
for (int i = 1; i <= num; ++i) {
list.add(new Object());
}
System.out.print(" 【已經生產產品數】 :" + num);
System.out.println(" 【現倉儲量為】 :" + list.size());
// 喚醒其他所有執行緒
full.signalAll();
empty.signalAll();
// 釋放鎖
lock.unlock();
}
// 消費 num 個產品
public void consume(int num) {
// 獲得鎖
lock.lock();
// 如果倉庫儲存量不足
while (list.size() < num) {
System.out.print(" 【要消費的產品數量】 :" + num);
System.out.println(" 【庫存量】 :" + list.size() + " 暫時不能執行生產任務 !");
try {
// 由於條件不滿足,消費阻塞
empty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 消費條件滿足情況下,消費 num 個產品
for (int i = 1; i <= num; ++i) {
list.remove();
}
System.out.print(" 【已經消費產品數】 :" + num);
System.out.println(" 【現倉儲 ) 量為】 :" + list.size());
// 喚醒其他所有執行緒
full.signalAll();
empty.signalAll();
// 釋放鎖
lock.unlock();
}
// set/get 方法
public int getMAX_SIZE() {
return MAX_SIZE;
}
public LinkedList getList() {
return list;
}
public void setList(LinkedList list) {
this.list = list;
}
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913892/viewspace-2658724/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 好程式設計師Java培訓分享Java多執行緒併發程式設計師Java執行緒
- 多執行緒程式設計,處理多執行緒的併發問題(執行緒池)執行緒程式設計
- 好程式設計師Java培訓分享Java多執行緒程式設計師Java執行緒
- 好程式設計師Java培訓分享Java多執行緒常見面試問題程式設計師Java執行緒面試
- 好程式設計師Java學習路線分享多執行緒概念程式設計師Java執行緒
- Java多執行緒/併發12、多執行緒訪問static變數Java執行緒變數
- 多執行緒併發程式設計“鎖”事執行緒程式設計
- 好程式設計師Java教程分享Java多執行緒常見面試題程式設計師Java執行緒面試題
- iOS多執行緒之併發程式設計-4iOS執行緒程式設計
- 【多執行緒高併發程式設計】二 實現多執行緒的幾種方式執行緒程式設計
- 併發程式設計之多執行緒執行緒安全程式設計執行緒
- 好程式設計師大資料學習路線分享多執行緒學習筆記程式設計師大資料執行緒筆記
- 好程式設計師分享大資料教程之執行緒高階部分程式設計師大資料執行緒
- 併發程式設計之:執行緒程式設計執行緒
- 好程式設計師web前端分享如何理解JS的單執行緒程式設計師Web前端JS執行緒
- 多執行緒高併發程式設計(9) -- CopyOnWrite寫入時複製執行緒程式設計
- Java程式設計師面試中的多執行緒問題Java程式設計師面試執行緒
- Java多執行緒與併發程式設計總結(一)Java執行緒程式設計
- 併發程式設計與執行緒安全程式設計執行緒
- java併發程式設計——執行緒池Java程式設計執行緒
- 從執行緒到併發程式設計執行緒程式設計
- java併發程式設計——執行緒同步Java程式設計執行緒
- Java併發程式設計:Java執行緒Java程式設計執行緒
- 如何解決多程式或多執行緒併發的問題執行緒
- 好程式設計師大資料學習路線分享大資料之執行緒程式設計師大資料執行緒
- Java 多執行緒與併發程式設計 · Java 工程師必知必會Java執行緒程式設計工程師
- C++11併發程式設計:多執行緒std::threadC++程式設計執行緒thread
- 程式設計體系結構(05):Java多執行緒併發程式設計Java執行緒
- Java 多執行緒併發程式設計之 Synchronized 關鍵字Java執行緒程式設計synchronized
- java併發程式設計:執行緒池的使用Java程式設計執行緒
- Java併發程式設計之執行緒安全、執行緒通訊Java程式設計執行緒
- Java併發程式設計(二)如何保證執行緒同時/交替執行Java程式設計執行緒
- java併發程式設計 | 執行緒詳解Java程式設計執行緒
- 併發程式設計——如何終止執行緒程式設計執行緒
- 併發程式設計之:執行緒池(一)程式設計執行緒
- 併發程式設計之多執行緒基礎程式設計執行緒
- Java併發程式設計-執行緒基礎Java程式設計執行緒
- HashMap多執行緒併發問題分析HashMap執行緒