JavaShuo
欄目
標籤
Java併發教程-5保護塊(Guarded Blocks)
時間 2019-11-07
標籤
java
併發
教程
保護
guarded
blocks
欄目
Java
简体版
原文
原文鏈接
多線程之間常常須要協同工做,最多見的方式是使用Guarded Blocks,它循環檢查一個條件(一般初始值爲true),直到條件發生變化才跳出循環繼續執行。在使用Guarded Blocks時有如下幾個步驟須要注意:
假設guardedJoy()方法必需要等待另外一線程爲共享變量joy設值才能繼續執行。那麼理論上能夠用一個簡單的條件循環來實現,但在等待過程當中guardedJoy方法不停的檢查循環條件其實是一種資源浪費。
Java代碼
public
void
guardedJoy() {
// Simple loop guard. Wastes
// processor time. Don't do this!
while
(!joy) {}
System.out.println(
"Joy has been achieved!"
);
}
更加高效的方法是調用Object.wait將當前線程掛起,直到有另外一線程發起事件通知(儘管通知的事件不必定是當前線程等待的事件)。
Java代碼
public
synchronized
void
guardedJoy() {
// This guard only loops once for each special event, which may not
// be the event we're waiting for.
while
(!joy) {
try
{
wait();
}
catch
(InterruptedException e) {}
}
System.out.println(
"Joy and efficiency have been achieved!"
);
}
注意:必定要在循環裏面調用wait方法,不要想固然的認爲線程喚醒後循環條件必定發生了改變。
和其餘能夠暫停線程執行的方法同樣,wait方法會拋出InterruptedException,在上面的例子中,由於咱們關心的是joy的值,因此忽略了InterruptedException。
爲何guardedJoy是synchronized方法?假設d是用來調用wait的對象,當一個線程調用d.wait,它必需要擁有d的內部鎖(不然會拋出異常),得到d的內部鎖的最簡單方法是在一個synchronized方法裏面調用wait。
當一個線程調用wait方法時,它釋放鎖並掛起。而後另外一個線程請求並得到這個鎖並調用
Object.notifyAll
通知全部等待該鎖的線程。
Java代碼
public
synchronized
notifyJoy() {
joy =
true
;
notifyAll();
}
當第二個線程釋放這個該鎖後,第一個線程再次請求該鎖,從wait方法返回並繼續執行。
注意:還有另一個通知方法,notify(),它只會喚醒一個線程。但因爲它並不容許指定哪個線程被喚醒,因此通常只在大規模併發應用(即系統有大量類似任務的線程)中使用。由於對於大規模併發應用,咱們其實並不關心哪個線程被喚醒。
如今咱們使用Guarded blocks建立一個生產者/消費者應用。這類應用須要在兩個線程之間共享數據:生產者生產數據,消費者使用數據。兩個線程經過共享對象通訊。在這裏,線程協同工做的關鍵是:生產者發佈數據以前,消費者不可以去讀取數據;消費者沒有讀取舊數據前,生產者不能發佈新數據。
在下面的例子中,數據經過
Drop
對象共享的一系列文本消息:
Java代碼
public
class
Drop {
// Message sent from producer
// to consumer.
private
String message;
// True if consumer should wait
// for producer to send message,
// false if producer should wait for
// consumer to retrieve message.
private
boolean
empty =
true
;
public
synchronized
String take() {
// Wait until message is
// available.
while
(empty) {
try
{
wait();
}
catch
(InterruptedException e) {}
}
// Toggle status.
empty =
true
;
// Notify producer that
// status has changed.
notifyAll();
return
message;
}
public
synchronized
void
put(String message) {
// Wait until message has
// been retrieved.
while
(!empty) {
try
{
wait();
}
catch
(InterruptedException e) {}
}
// Toggle status.
empty =
false
;
// Store message.
this
.message = message;
// Notify consumer that status
// has changed.
notifyAll();
}
}
Producer
是生產者線程,發送一組消息,字符串DONE表示全部消息都已經發送完成。爲了模擬現實狀況,生產者線程還會在消息發送時隨機的暫停。
Java代碼
import
java.util.Random;
public
class
Producer
implements
Runnable {
private
Drop drop;
public
Producer(Drop drop) {
this
.drop = drop;
}
public
void
run() {
String importantInfo[] = {
"Mares eat oats"
,
"Does eat oats"
,
"Little lambs eat ivy"
,
"A kid will eat ivy too"
};
Random random =
new
Random();
for
(
int
i =
0
;
i < importantInfo.length;
i++) {
drop.put(importantInfo[i]);
try
{
Thread.sleep(random.nextInt(
5000
));
}
catch
(InterruptedException e) {}
}
drop.put(
"DONE"
);
}
}
Consumer
是消費者線程,讀取消息並打印出來,直到讀取到字符串DONE爲止。消費者線程在消息讀取時也會隨機的暫停。
Java代碼
import
java.util.Random;
public
class
Consumer
implements
Runnable {
private
Drop drop;
public
Consumer(Drop drop) {
this
.drop = drop;
}
public
void
run() {
Random random =
new
Random();
for
(String message = drop.take();
! message.equals(
"DONE"
);
message = drop.take()) {
System.out.format(
"MESSAGE RECEIVED: %s%n"
, message);
try
{
Thread.sleep(random.nextInt(
5000
));
}
catch
(InterruptedException e) {}
}
}
}
ProducerConsumerExample
是主線程,它啓動生產者線程和消費者線程。
Java代碼
public
class
ProducerConsumerExample {
public
static
void
main(String[] args) {
Drop drop =
new
Drop();
(
new
Thread(
new
Producer(drop))).start();
(
new
Thread(
new
Consumer(drop))).start();
}
}
注意:Drop類是用來演示Guarded Blocks如何工做的。爲了不從新發明輪子,當你嘗試建立本身的共享數據對象時,請查看
Java Collections Framework
中已有的數據結構。如需更多信息,請參考
Questions and Exercises
。
相關文章
1.
java併發編程之Guarded Suspention
2.
保護性暫掛模式(Guarded Suspension)
3.
C++11 併發編程教程 - Part 2 : 保護共享數據
4.
受保護Hyper-V環境和受保護虛擬機Guarded fabric and shielded VMs
5.
java 同步塊(Java Synchronized Blocks)
6.
5、Java併發編程:Lock
7.
【Java併發.5】基礎構建模塊
8.
Java併發編程教程
9.
Java程序的保護
10.
Excel組件Spire.XLS 教程:保護和取消保護工做表
更多相關文章...
•
Rust 併發編程
-
RUST 教程
•
XSL-FO 教程
-
XSL-FO 教程
•
Java 8 Stream 教程
•
JDK13 GA發佈:5大特性解讀
相關標籤/搜索
Java併發.5
guarded
blocks
保護
Java 併發編程
Java併發編程
java併發
Java併發.6
Java併發.4
Java-併發
Java
PHP教程
Thymeleaf 教程
Spring教程
教程
java
開發工具
0
分享到微博
分享到微信
分享到QQ
每日一句
每一个你不满意的现在,都有一个你没有努力的曾经。
最新文章
1.
Android Studio3.4中出現某個項目全部亂碼的情況之解決方式
2.
Packet Capture
3.
Android 開發之 仿騰訊視頻全部頻道 RecyclerView 拖拽 + 固定首個
4.
rg.exe佔用cpu導致卡頓解決辦法
5.
X64內核之IA32e模式
6.
DIY(也即Build Your Own) vSAN時,選擇SSD需要注意的事項
7.
選擇深圳網絡推廣外包要注意哪些問題
8.
店鋪運營做好選款、測款的工作需要注意哪些東西?
9.
企業找SEO外包公司需要注意哪幾點
10.
Fluid Mask 摳圖 換背景教程
本站公眾號
歡迎關注本站公眾號,獲取更多信息
相關文章
1.
java併發編程之Guarded Suspention
2.
保護性暫掛模式(Guarded Suspension)
3.
C++11 併發編程教程 - Part 2 : 保護共享數據
4.
受保護Hyper-V環境和受保護虛擬機Guarded fabric and shielded VMs
5.
java 同步塊(Java Synchronized Blocks)
6.
5、Java併發編程:Lock
7.
【Java併發.5】基礎構建模塊
8.
Java併發編程教程
9.
Java程序的保護
10.
Excel組件Spire.XLS 教程:保護和取消保護工做表
>>更多相關文章<<