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.
.Net core webapi2.1生成exe可执行文件
2.
查看dll信息工具-oleview
3.
c++初学者
4.
VM下载及安装
5.
win10下如何安装.NetFrame框架
6.
WIN10 安装
7.
JAVA的环境配置
8.
idea全局配置maven
9.
vue项目启动
10.
SVN使用-Can't remove directoryXXXX,目录不是空的,项目报错,有红叉
本站公众号
欢迎关注本站公众号,获取更多信息
相关文章
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 教程:保护和取消保护工做表
>>更多相关文章<<