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.
Mud Puddles ( bfs )
2.
ReSIProcate環境搭建
3.
SNAT(IP段)和配置網絡服務、網絡會話
4.
第8章 Linux文件類型及查找命令實踐
5.
AIO介紹(八)
6.
中年轉行互聯網,原動力、計劃、行動(中)
7.
詳解如何讓自己的網站/APP/應用支持IPV6訪問,從域名解析配置到服務器配置詳細步驟完整。
8.
PHP 5 構建系統
9.
不看後悔系列!Rocket MQ 使用排查指南(附網盤鏈接)
10.
如何簡單創建虛擬機(CentoOS 6.10)
本站公眾號
歡迎關注本站公眾號,獲取更多信息
相關文章
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 教程:保護和取消保護工做表
>>更多相關文章<<