Java并发编程实例--15.在同步代码块中使用条件
并发编程中有个经典问题:
生产消费者问题。
我们有一个数据缓冲区,一个或多个生产者往其中存入对象,另外一个或多个消费者从中取走。
因此,该数据缓冲区是一个共享数据结构,我们需要对其添加读取同步机制,但是我们还需要一些限制。
如果缓冲区满了,生产者不能继续向其中写入;反过来如果缓冲区空了,消费者也不能继续读取。
对于这种情况,Java提供了wait(),notify()和notifyAll()方法。
一个线程可以在同步代码块中调用wait()方法。如果它在同步块之外调用wait()方法,JVM将抛出IllegalMonitorStateException。
当线程调用wait()方法,JVM将该线程睡眠并且释放控制同步代码块的对象,并允许其他线程去执行。
如果需要再次唤醒该线程,只需要调用notify()或notifyAll()方法。
本例中,你将学习如何使用synchronized关键字和wait(), notify(), and notifyAll()方法去实现生产-消费者问题。
缓冲区类:
EventStorage.java
package com.dylan.thread.ch2.c03.task;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
/**
* This class implements an Event storage. Producers will storage
* events in it and Consumers will process them. An event will
* be a java.util.Date object
*
*/
public class EventStorage {
/**
* Maximum size of the storage
*/
private int maxSize;
/**
* Storage of events
*/
private List<Date> storage;
/**
* Constructor of the class. Initializes the attributes.
*/
public EventStorage(){
maxSize=10;
storage=new LinkedList<>();
}
/**
* This method creates and storage an event.
*/
public synchronized void set(){
while (storage.size()==maxSize){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.add(new Date());
System.out.printf("Set: %d",storage.size());
notify();
}
/**
* This method delete the first event of the storage.
*/
public synchronized void get(){
while (storage.size()==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Get: %d: %s",storage.size(),((LinkedList<?>)storage).poll());
notify();
}
}
生产者:
Producer.java
package com.dylan.thread.ch2.c03.task;
/**
* This class implements a producer of events.
*
*/
public class Producer implements Runnable {
/**
* Store to work with
*/
private EventStorage storage;
/**
* Constructor of the class. Initialize the storage.
* @param storage The store to work with
*/
public Producer(EventStorage storage){
this.storage=storage;
}
/**
* Core method of the producer. Generates 100 events.
*/
@Override
public void run() {
for (int i=0; i<100; i++){
storage.set();
}
}
}
消费者:
Consumer.java
package com.dylan.thread.ch2.c03.task;
/**
* This class implements a consumer of events.
*
*/
public class Consumer implements Runnable {
/**
* Store to work with
*/
private EventStorage storage;
/**
* Constructor of the class. Initialize the storage
* @param storage The store to work with
*/
public Consumer(EventStorage storage){
this.storage=storage;
}
/**
* Core method for the consumer. Consume 100 events
*/
@Override
public void run() {
for (int i=0; i<100; i++){
storage.get();
}
}
}
主类:
Main.java
package com.dylan.thread.ch2.c03.core;
import com.dylan.thread.ch2.c03.task.Consumer;
import com.dylan.thread.ch2.c03.task.EventStorage;
import com.dylan.thread.ch2.c03.task.Producer;
/**
* Main class of the example
*/
public class Main {
/**
* Main method of the example
*/
public static void main(String[] args) {
// Creates an event storage
EventStorage storage=new EventStorage();
// Creates a Producer and a Thread to run it
Producer producer=new Producer(storage);
Thread thread1=new Thread(producer);
// Creates a Consumer and a Thread to run it
Consumer consumer=new Consumer(storage);
Thread thread2=new Thread(consumer);
// Starts the thread
thread2.start();
thread1.start();
}
}
运行结果:
Set: 1
Set: 2
Set: 3
Set: 4
Set: 5
Set: 6
Set: 7
Set: 8
Set: 9
Set: 10
Get: 10: Fri May 11 22:31:02 GMT+08:00 2018
Get: 9: Fri May 11 22:31:02 GMT+08:00 2018
Get: 8: Fri May 11 22:31:02 GMT+08:00 2018
Get: 7: Fri May 11 22:31:02 GMT+08:00 2018
Get: 6: Fri May 11 22:31:02 GMT+08:00 2018
Get: 5: Fri May 11 22:31:02 GMT+08:00 2018
Get: 4: Fri May 11 22:31:02 GMT+08:00 2018
Get: 3: Fri May 11 22:31:02 GMT+08:00 2018
Get: 2: Fri May 11 22:31:02 GMT+08:00 2018
Get: 1: Fri May 11 22:31:02 GMT+08:00 2018
Set: 1
Set: 2
...
Java并发编程实例--15.在同步代码块中使用条件的更多相关文章
- Java并发编程:线程的同步
Java并发编程:线程的同步 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...
- Java并发编程的4个同步辅助类
Java并发编程的4个同步辅助类(CountDownLatch.CyclicBarrier.Semphore.Phaser) @https://www.cnblogs.com/lizhangyong/ ...
- Java并发编程系列-(9) JDK 8/9/10中的并发
9.1 CompletableFuture CompletableFuture是JDK 8中引入的工具类,实现了Future接口,对以往的FutureTask的功能进行了增强. 手动设置完成状态 Co ...
- “全栈2019”Java多线程第二十一章:同步代码块产生死锁的例子
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第十八章:同步代码块双重判断详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- .NET中如何在同步代码块中调用异步方法
更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月2日. 在同步代码块中调用异步方法,方法有很多. 一.对于有返回值的Task 在同步代码块中直接访问 Task 的 Result ...
- wait、notify为什么要放在同步代码块中
等待方遵循的原则: 获取对象的锁,不满足条件就调用wait()方法,条件满足继续执行 通知方原则: 获取对象的锁,改变条件,然后notify 每个对象都有一个监视器锁,这个监视器锁的数据结构如下: w ...
- Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semphore、Phaser)
我在<jdk1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...
- Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semaphore、Phaser)
我在<JDK1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...
- Java并发编程(十三)同步容器类
同步容器类 Vector.HashTable,我用的很少:Vecotr的实现和ArrayList挺接近的,不同的是Vector中很多的方法都用synchronized进行了同步.在不强调线程安全地时候 ...
随机推荐
- 抓取java堆栈失败的思考-Safepoint等的学习
抓取java堆栈失败的思考-Safepoint等的学习 背景 前期解决问题都是靠抓取进程堆栈 jstack,后者是jmap到内存dump的方式来进行分析. 最近连续有两个比较大的项目出现了抓取dump ...
- [转帖]Elasticsearch 的 30 个调优最佳实践!
Elasticsearch 的 30 个调优最佳实践! https://zhuanlan.zhihu.com/p/406264041 ES 发布时带有的默认值,可为 es 的开箱即用带来很好的体验.全 ...
- [转帖]Windows磁盘性能压测(1)-DiskSpd
http://www.manongjc.com/detail/59-xrydhtisrajqsxn.html 本文章向大家介绍Windows磁盘性能压测(1)-DiskSpd,主要内容包括其使用实例. ...
- [转帖]LTP使用和分析
一.安装及编译流程 1.下载LTP LTP 项目目前位于 GitHub,项目地址:https://github.com/linux-test-project/ltp . 获取最新版可以执行以下命令: ...
- Linux 通过命令方式反编译jar包的方法
第一步: 复制jar包到指定路径. find . -iname "*.jar" -exec scp {} /root/bf/ \; 第二步: 解压缩jar包解压缩出来class文件 ...
- 【实践篇】最全的【DDD领域建模】小白学习手册(文末附资料)
导读 DDD领域建模被各个大小厂商提起并应用,而每个人都有自己的理解,本文就是针对小白,系统地讲解DDD到底是什么,解决了什么问题,及一些建议和实践.本文主要是思想的一种碰撞和分享,希望能对朋友们有所 ...
- 替换 &开头。;结尾之间的内容。用空格代替他们
替换 &开头.;结尾之间的内容.用空格代替他们 var regExp = /\&.*?\;/g; var str = '123&asdsa;dqwe'; str = str.r ...
- 【VictoriaMetrics的vmbackupmanager】这个一年卖 2 万美元的功能,我做出来了
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 1.背景 在可观测领域的 metrics 解决方案中,Vi ...
- dump分析器winbdg
工具: winbdg WinDBG不是专门用于调试.Net程序的工具,它更偏向于底层,可用于内核和驱动调试.进行普通的.Net程序调试还是使用微软专为.Net开发的调试工具MDBG更方便一些.但是Wi ...
- Centos7把home目录下多余的空间转移到/根目录下
通过df-h发现,根目录只有32G,而home目录可用的,居然有142G.我现在想分出70G给根目录 把你需要挂载的机器的逻辑卷记住(上面的图,左边是逻辑卷,右边是虚拟磁盘) /dev/mapper/ ...