java guardedby_Oracle官方并发教程之Guarded Blocks
原文连接,译文连接,译者:Greester,校对:郑旭东
多线程之间经常需要协同工作,最常见的方式是使用Guarded Blocks,它循环检查一个条件(通常初始值为true),直到条件发生变化才跳出循环继续执行。在使用Guarded Blocks时有以下几个步骤需要注意:
假设guardedJoy()方法必须要等待另一线程为共享变量joy设值才能继续执行。那么理论上可以用一个简单的条件循环来实现,但在等待过程中guardedJoy方法不停的检查循环条件实际上是一种资源浪费。
public void guardedJoy() {
// Simple loop guard. Wastes
// processor time. Don't do this!
while(!joy) {}
System.out.println("Joy has been achieved!");
}
更加高效的方法是调用Object.wait将当前线程挂起,直到有另一线程发起事件通知(尽管通知的事件不一定是当前线程等待的事件)。
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方法时,它释放锁并挂起。然后另一个线程请求并获得这个锁并调用
public synchronized notifyJoy() {
joy = true;
notifyAll();
}
当第二个线程释放这个该锁后,第一个线程再次请求该锁,从wait方法返回并继续执行。
注意:还有另外一个通知方法,notify(),它只会唤醒一个线程。但由于它并不允许指定哪一个线程被唤醒,所以一般只在大规模并发应用(即系统有大量相似任务的线程)中使用。因为对于大规模并发应用,我们其实并不关心哪一个线程被唤醒。
现在我们使用Guarded blocks创建一个生产者/消费者应用。这类应用需要在两个线程之间共享数据:生产者生产数据,消费者使用数据。两个线程通过共享对象通信。在这里,线程协同工作的关键是:生产者发布数据之前,消费者不能够去读取数据;消费者没有读取旧数据前,生产者不能发布新数据。
在下面的例子中,数据通过Drop对象共享的一系列文本消息:
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表示所有消息都已经发送完成。为了模拟现实情况,生产者线程还会在消息发送时随机的暂停。
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为止。消费者线程在消息读取时也会随机的暂停。
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) {}
}
}
}
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。
java guardedby_Oracle官方并发教程之Guarded Blocks相关推荐
- java jni helloword_JNI入门教程之HelloWorld篇
JNI入门教程之HelloWorld篇 来源:互联网 宽屏版 评论 2008-05-31 09:07:11 本文讲述如何使用JNI技术实现HelloWorld,目的是让读者熟悉JNI的机制并编写第 ...
- java 时间戳_Java并发编程之CAS三CAS的缺点 及解决办法
Java并发编程之CAS第三篇-CAS的缺点 通过前两篇的文章介绍,我们知道了CAS是什么以及查看源码了解CAS原理.那么在多线程并发环境中,的缺点是什么呢?这篇文章我们就来讨论讨论 本篇是<凯 ...
- java的condition_java并发编程之Condition
引言 在java中,对于任意一个java对象,它都拥有一组定义在java.lang.Object上监视器方法,包括wait(),wait(long timeout),notify(),notifyAl ...
- java master work_并发编程之Master-Worker模式
我们知道,单个线程计算是串行的,只有等上一个任务结束之后,才能执行下一个任务,所以执行效率是比较低的. 那么,如果用多线程执行任务,就可以在单位时间内执行更多的任务,而Master-Worker就是多 ...
- java happens before_Java并发编程之happens-before
happens-before是JMM最核心的概念,理解happens-before是理解JMM的关键. 一.JMM的设计 首先,让我们先分析一下JMM的设计意图.从JMM的设计者的角度,在设计JMM的 ...
- java 如何连接oracle_oracle教程之java连接oracle_java如何连接oracle数据库?
java与oracle的接口: 在数据库中运行JAVA可以说是ORACLE8i的最令人激动的新特性.在你创建的使用ORACLE8i 数据库的应用程序中,你可以使用与JAVA有关的新特征,轻松的将程序发 ...
- JAVA常用框架系列教程之Spring(附视频)
大家好,框架作为程序员开发重要的学习部分,在java开发中,框架的学习也尤为的重要,框架不仅可以帮助大家高效的进行开发工作,更加能够优化工作步骤,从而提高开发人员的工作效率.为帮助Java编程的初学者 ...
- java线程安全的set_Java并发编程之set集合的线程安全类你知道吗
Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥并发编程学习>系列之<并发集合系列& ...
- java jdbc 教程_java JDBC系列教程之JDBC类的简析与JDBC的基础操作
什么是JDBC? 概念:JAVA Database Connectivity Javas数据库连接,Java语言操作数据库接口,然后由各个数据库厂商去实现这个接口,提供数据库驱动java包,我们可以使 ...
- zbb20180929 thread java并发编程之Condition
java并发编程之Condition 引言 在java中,对于任意一个java对象,它都拥有一组定义在java.lang.Object上监视器方法,包括wait(),wait(long timeout ...
最新文章
- 句法分析语料:哈尔滨工业大学SemEval、清华大学树库
- java实现将A表数据转移到B表_解决用B表跟新A表数据,如果A表中没有,则把B表的数据插入A表(merge into)...
- 创建electron应用
- 建智能工厂,可从这6个方面着手!
- 分布式架构中一致性解决方案——Zookeeper集群搭建
- [Swift]LeetCode859. 亲密字符串 | Buddy Strings
- 正则匹配括号里面的内容不包括括号_python正则表达式
- 按照标题排序mysql_Oracle EBS Form中实现点击列标题进行排序
- Unity资源打包之Assetbundle
- php简单富文本,JS简易版富文本编辑器实现代码
- 使用java jpcap实现网络嗅探器
- 提升用户体验的40个Firefox 4扩展
- unity 裙子摆动_Unity中实现MMD效果
- 6个Web前端值得收藏很实用的菜单模板(上)
- 基于Java+SpringBoot+Thymeleaf+Mysql在线购物网站商城系统设计实现
- java毫秒数_Java中的毫秒数
- json parser类的使用
- 前端特效demo | 一起围观 10 种创意时钟 1
- 问题 C: 小写转大写
- 从小程序到小程序云开发
热门文章
- 1.19.10.Flink SQL工程案例\Flink批式处理\自定义函数\Window窗口计算\将DataSet数据转成Table数据\将Table数据转成DataSet等
- 【BP-GA】基于GA的BP神经网络优化算法
- CCF-分蛋糕-Java
- 谷歌命名工具_Google地图正在重命名整个社区
- chrome浏览器主页变成hao123
- ceph 代码分析 读_Ceph代码分析
- 使用html2canvas实现超出浏览器部分截图
- 网管系统测试学习——传输网下一代综合网管系统测试
- 如何看待2022年秋招后开端岗一片红海?
- win7设置网络共享(ICS共享)