Java多執行緒/併發05、synchronized應用例項:執行緒間操作共享資料
電商平臺中最重要的一點就是賣東西。同個商品不能無限制的賣下去的,因為商品有庫存量,超過庫存就不能賣了。
這裡,約定一個規則,下單使庫存減n,取消訂單使庫存加m。庫存數量不可以小於0。
假設平臺上同時有很多使用者在操作,在不考慮效率的情況下,我們用同步方法來模擬這個場景。
首先寫一個訂單處理類:
class OrderHandler{
/*初始某商品庫存量*/
int StockSomeGoodsNum=200;
/*使用者下單*/
public void Produce(int n){
/*step1:判斷可用庫存操作*/
if((StockSomeGoodsNum-n)>=0){
/*為了更好體現執行緒間的競爭,讓程式休眠一下*/
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*step2:執行減少庫存操作*/
StockSomeGoodsNum-=n;
System.out.println("使用者" + Thread.currentThread().getName()
+ "成功購買商品:" + String.valueOf(n)+"個,庫存剩餘"+StockSomeGoodsNum+"個");
}else{
System.out.println("使用者" + Thread.currentThread().getName()
+ "下單失敗,庫存不足" + String.valueOf(n)+"個,庫存剩餘"+StockSomeGoodsNum+"個");
}
}
/*使用者取消訂單*/
public void Cancel(int n){
StockSomeGoodsNum+=n;
System.out.println("使用者" + Thread.currentThread().getName()
+ "取消購買商品:" + String.valueOf(n)+"個,庫存剩餘"+StockSomeGoodsNum+"個");
}
}
可以看到類中的兩個方法都會操作StockSomeGoodsNum
變數
在使用者下單方法void Produce(int n)中,首先判斷庫存數量夠不夠,如果夠了對庫存數量進行減少操作。這裡涉及兩個步驟:判斷庫存、減少庫存。這兩個步驟組成一個事務,是不允許分開和打亂的。但現在是多個執行緒併發執行,就有可能在這兩個步驟之間,有別的執行緒執行了增減庫存操作。
現在在主函式中開啟多個執行緒來模擬使用者下單和取消訂單的操作:
public static void main(String[] args) {
final OrderHandler orderHandler=new OrderHandler();
/*開啟10個執行緒,模擬10個使用者進行下單操作*/
for(int i=0;i<10;i++){
new Thread(new Runnable() {
public void run() {
/*每個人購買商品數量為25個*/
orderHandler.Produce(25);
}
}).start();
}
/*開啟5個執行緒,模擬5個使用者在進行取消訂單操作*/
for(int i=0;i<5;i++){
new Thread(new Runnable() {
public void run() {
/*每個取消訂單中包含的商品數為3個*/
orderHandler.Cancel(3);
}
}).start();
}
}
}
執行結果:
使用者Thread-10取消購買商品:3個,庫存剩餘203個
使用者Thread-12取消購買商品:3個,庫存剩餘209個
使用者Thread-11取消購買商品:3個,庫存剩餘206個
使用者Thread-13取消購買商品:3個,庫存剩餘212個
使用者Thread-14取消購買商品:3個,庫存剩餘215個
使用者Thread-1成功購買商品:25個,庫存剩餘165個
使用者Thread-2成功購買商品:25個,庫存剩餘140個
使用者Thread-0成功購買商品:25個,庫存剩餘165個
使用者Thread-3成功購買商品:25個,庫存剩餘115個
使用者Thread-4成功購買商品:25個,庫存剩餘65個
使用者Thread-5成功購買商品:25個,庫存剩餘65個
使用者Thread-8成功購買商品:25個,庫存剩餘-10個
使用者Thread-6成功購買商品:25個,庫存剩餘15個
使用者Thread-7成功購買商品:25個,庫存剩餘-10個
使用者Thread-9成功購買商品:25個,庫存剩餘-35個
出現了負數,說明在判斷庫存、減少庫存的兩個步驟中有其它執行緒執行,導致結果不正確。現在我們在Produce()和Cancle()方法前加上synchronized關鍵字,讓它們成為同步方法。
再次執行結果:
使用者Thread-0成功購買商品:25個,庫存剩餘175個
使用者Thread-14取消購買商品:3個,庫存剩餘178個
使用者Thread-13取消購買商品:3個,庫存剩餘181個
使用者Thread-12取消購買商品:3個,庫存剩餘184個
使用者Thread-11取消購買商品:3個,庫存剩餘187個
使用者Thread-10取消購買商品:3個,庫存剩餘190個
使用者Thread-9成功購買商品:25個,庫存剩餘165個
使用者Thread-8成功購買商品:25個,庫存剩餘140個
使用者Thread-7成功購買商品:25個,庫存剩餘115個
使用者Thread-6成功購買商品:25個,庫存剩餘90個
使用者Thread-5成功購買商品:25個,庫存剩餘65個
使用者Thread-4成功購買商品:25個,庫存剩餘40個
使用者Thread-3成功購買商品:25個,庫存剩餘15個
使用者Thread-2下單失敗,庫存不足25個,庫存剩餘15個
使用者Thread-1下單失敗,庫存不足25個,庫存剩餘15個
結論:
各個執行緒間能保持如此好的協作,其關鍵原因就是OrderHandler類中的方法都是synchronized同步方法,因此他們有共同的鎖:this,當一個執行緒執行時,其它執行緒都被阻塞,這樣保證了程式的正常執行。
synchronized同步方法雖然很安全,但效率也很低。synchronized同步方法是序列執行的,多個執行緒排隊,並沒有併發執行。因此在實際業務開發中要注意。
相關文章
- JAVA多執行緒併發Java執行緒
- Java多執行緒之執行緒同步【synchronized、Lock、volatitle】Java執行緒synchronized
- java多執行緒3:synchronizedJava執行緒synchronized
- Java多執行緒(三):SynchronizedJava執行緒synchronized
- java多執行緒之(synchronized)Java執行緒synchronized
- java多執行緒與併發 - 執行緒池詳解Java執行緒
- Java多執行緒之二(Synchronized)Java執行緒synchronized
- 多執行緒併發篇——如何停止執行緒執行緒
- 【多執行緒與高併發3】常用鎖例項執行緒
- Java進階05 多執行緒Java執行緒
- java多執行緒5:執行緒間的通訊Java執行緒
- 併發與多執行緒之執行緒安全篇執行緒
- 多執行緒與高併發(二)執行緒安全執行緒
- Java多執行緒-執行緒中止Java執行緒
- Java多執行緒之synchronized詳解Java執行緒synchronized
- Java多執行緒之synchronized理論Java執行緒synchronized
- Java多執行緒——synchronized的使用示例Java執行緒synchronized
- 多執行緒與高併發(一)多執行緒入門執行緒
- 多執行緒併發鎖分類以及簡單例項執行緒單例
- Java 併發:執行緒、執行緒池和執行器全面教程Java執行緒
- Java併發 之 執行緒池系列 (1) 讓多執行緒不再坑爹的執行緒池Java執行緒
- pytest(13)-多執行緒、多程式執行用例執行緒
- Java高併發與多執行緒(二)-----執行緒的實現方式Java執行緒
- 多執行緒應用執行緒
- Java併發(四)----執行緒執行原理Java執行緒
- Qt中的多執行緒與執行緒池淺析+例項QT執行緒
- 05.java多執行緒問題Java執行緒
- Java多執行緒-執行緒狀態Java執行緒
- Java多執行緒-執行緒通訊Java執行緒
- java多執行緒9:執行緒池Java執行緒
- java 多執行緒守護執行緒Java執行緒
- Java多執行緒(2)執行緒鎖Java執行緒
- 【java多執行緒】(二)執行緒停止Java執行緒
- Java多執行緒之執行緒中止Java執行緒
- 多執行緒操作執行緒
- java多執行緒與併發 - 併發工具類Java執行緒
- 多執行緒與高併發(三)synchronized關鍵字執行緒synchronized
- 程式設計體系結構(05):Java多執行緒併發程式設計Java執行緒
- Java多執行緒與併發之ThreadLocalJava執行緒thread