并发编程中有个经典问题:
生产消费者问题。

我们有一个数据缓冲区,一个或多个生产者往其中存入对象,另外一个或多个消费者从中取走。

因此,该数据缓冲区是一个共享数据结构,我们需要对其添加读取同步机制,但是我们还需要一些限制。

如果缓冲区满了,生产者不能继续向其中写入;反过来如果缓冲区空了,消费者也不能继续读取。





对于这种情况,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.在同步代码块中使用条件的更多相关文章

  1. Java并发编程:线程的同步

    Java并发编程:线程的同步 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...

  2. Java并发编程的4个同步辅助类

    Java并发编程的4个同步辅助类(CountDownLatch.CyclicBarrier.Semphore.Phaser) @https://www.cnblogs.com/lizhangyong/ ...

  3. Java并发编程系列-(9) JDK 8/9/10中的并发

    9.1 CompletableFuture CompletableFuture是JDK 8中引入的工具类,实现了Future接口,对以往的FutureTask的功能进行了增强. 手动设置完成状态 Co ...

  4. “全栈2019”Java多线程第二十一章:同步代码块产生死锁的例子

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  5. “全栈2019”Java多线程第十八章:同步代码块双重判断详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  6. .NET中如何在同步代码块中调用异步方法

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月2日. 在同步代码块中调用异步方法,方法有很多. 一.对于有返回值的Task 在同步代码块中直接访问 Task 的 Result ...

  7. wait、notify为什么要放在同步代码块中

    等待方遵循的原则: 获取对象的锁,不满足条件就调用wait()方法,条件满足继续执行 通知方原则: 获取对象的锁,改变条件,然后notify 每个对象都有一个监视器锁,这个监视器锁的数据结构如下: w ...

  8. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semphore、Phaser)

    我在<jdk1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  9. Java并发编程的4个同步辅助类(CountDownLatch、CyclicBarrier、Semaphore、Phaser)

    我在<JDK1.5引入的concurrent包>中,曾经介绍过CountDownLatch.CyclicBarrier两个类,还给出了CountDownLatch的演示案例.这里再系统总结 ...

  10. Java并发编程(十三)同步容器类

    同步容器类 Vector.HashTable,我用的很少:Vecotr的实现和ArrayList挺接近的,不同的是Vector中很多的方法都用synchronized进行了同步.在不强调线程安全地时候 ...

随机推荐

  1. [转帖]linux audit审计(7-1)--读懂audit日志

    https://www.cnblogs.com/xingmuxin/p/8807774.html  auid=0 auid记录Audit user ID,that is the loginuid.当我 ...

  2. [转帖]使用S3F3在Linux实例上挂载Bucket

    https://docs.jdcloud.com/cn/object-storage-service/s3fs S3F3是基于FUSE的文件系统,允许Linux 挂载Bucket在本地文件系统,S3f ...

  3. CentOS测试yum update.

    我有一台centos7 1611 的机器 想着升级一下 简单进行测试 1. 操作系统的信息为: [root@CentOS1611 yum.repos.d]# uname -a Linux CentOS ...

  4. Linux 通过命令方式反编译jar包的方法

    第一步: 复制jar包到指定路径. find . -iname "*.jar" -exec scp {} /root/bf/ \; 第二步: 解压缩jar包解压缩出来class文件 ...

  5. 【如何提高IT运维效率】深度解读京东云基于NLP的运维日志异常检测AIOps落地实践

    作者:京东科技  张宪波.张静.李东江 基于NLP技术对运维日志聚类,从日志角度快速发现线上业务问题 日志在IT行业中被广泛使用,日志的异常检测对于识别系统的运行状态至关重要.解决这一问题的传统方法需 ...

  6. golang 中使用 writev (sendmsg) 系统调用来一次发送多块数据

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 writev,或者说 sendmsg 等系统调用,能够发送 ...

  7. 语义检索系统:基于Milvus 搭建召回系统抽取向量进行检索,加速索引

    语义检索系统:基于Milvus 搭建召回系统抽取向量进行检索,加速索引 目标:使用 Milvus 搭建召回系统,然后使用训练好的语义索引模型,抽取向量,插入到 Milvus 中,然后进行检索. 语义搜 ...

  8. 一些提供办公效率的软件(clover、f.lux、幕布),老赞了!

    1.clover 链接:http://cn.ejie.me/ Clover是由异次元的读者ejie团队开发的一款电脑窗口标签化工具.Clover是电脑中资源管理器的一个扩展程序,可以为其增加多标签页的 ...

  9. 3.0 熟悉IDAPro静态反汇编器

    IDA Pro 是一种功能强大且灵活的反汇编工具,可以在许多领域中发挥作用,例如漏洞研究.逆向工程.安全审计和软件开发等,被许多安全专家和软件开发者用于逆向工程和分析二进制代码.它支持大量的二进制文件 ...

  10. vue下载本地文件 下载二进制流文件 兼容ie

    vue-cli2要下载的静态文件放在static目录下,vue-cli3则放在public目录下 ie不支持 h5 的download写法,故用以下写法 <el-button type=&quo ...