基本线程同步(四)在同步代码中使用条件
在同步代码中使用条件
在并发编程中的一个经典问题是生产者与消费者问题,我们有一个数据缓冲区,一个或多个数据的生产者在缓冲区存储数据,而一个或多个数据的消费者,把数据从缓冲区取出。
由于缓冲区是一个共享的数据结构,我们必须采用同步机制,比如synchronized关键字来控制对它的访问。但是我们有更多的限制因素,如果缓冲区是满的,生产者不能存储数据,如果缓冲区是空的,消费者不能取出数据。
对于这些类型的情况,Java在Object对象中提供wait(),notify(),和notifyAll() 方法的实现。一个线程可以在synchronized代码块中调用wait()方法。如果在synchronized代码块外部调用wait()方法,JVM会抛出IllegalMonitorStateException异常。当线程调用wait()方法,JVM让这个线程睡眠,并且释放控制 synchronized代码块的对象,这样,虽然它正在执行但允许其他线程执行由该对象保护的其他synchronized代码块。为了唤醒线程,你必 须在由相同对象保护的synchronized代码块中调用notify()或notifyAll()方法。
在这个指南中,你将学习如何通过使用synchronized关键字和wait()和notify(),notifyAll()方法实现生产者消费者问题。
准备工作
这个指南的例子使用Eclipse IDE实现。如果你使用Eclipse或其他IDE,如NetBeans,打开它并创建一个新的Java项目。
如何做…
按以下步骤来实现的这个例子:
1.创建EventStorage类,包括一个名为maxSize,类型为int的属性和一个名为storage,类型为LinkedList Date 的属性。
3. 实现synchronized方法set(),用来在storage上存储一个事件。首先,检查storage是否已满。如果满了,调用wait()方 法,直到storage有空的空间。在方法的尾部,我们调用notifyAll()方法来唤醒,所有在wait()方法上睡眠的线程。
4. 实现synchronized方法get(),用来在storage上获取一个事件。首先,检查storage是否有事件。如果没有,调用wait()方 法直到,storage有一些事件,在方法的尾部,我们调用notifyAll()方法来唤醒,所有在wait()方法上睡眠的线程。
它是如何工作的…
EventStorage 类的set()方法和get()方法是这个示例的关键。首先,set()方法检查storage属性是否有空闲空间。如果它满了,调用wait()方法等 待有空闲的空间。当其他线程调用notifyAll()方法,这个线程将被唤醒并且再次检查这个条件。这个notifyAll()方法并不保证线程会醒 来。这个过程是重复,直到storage有空闲空间,然后它可以生成一个新的事件并存储它。
get()方法的行为是相似的。首先,它检查storage是否有事件。如果EventStorage类是空的,调用wait()方法等待事件。当其他线程调用notifyAll()方法,这个线程将被唤醒并且再次检查这个条件直到storage有一些事件。
注释:在while循环中,你必须保持检查条件和调用wait()方法。你不能继续执行,直到这个条件为true。
不止这些…
synchronize关键字还有其他重要用法,请见其他指南中解释这个关键字使用的参见部分。
参见
在第2章,基本线程同步中在同步类中安排独立属性的食谱。
java并发多线程显式锁Condition条件简介分析与监视器 多线程下篇(四) java并发多线程显式锁Condition条件简介分析与监视器 多线程下篇(四) Lock接口提供了方法Condition newCondition();用于获取对应锁的条件,可以在这个条件对象上调用监视器方法 可以理解为,原本借助于synchronized关键字以及锁对象,配备了一个监视器
有的时候我们希望线程按照希望的顺序依次执行,比如线程A,B,C,按照顺序依次执行,这时候就要用到阻塞和唤醒,之前的时候我们学到过wait()和nofity/notifyAll()这两个方法,这里我们使用java.
ali清英 方腾飞,花名清英,英文名kiral,并发编程网创始人,支付宝技术专家,《Java并发编程的艺术》作者。
相关文章
- Java 多线程系列(8) —— 线程同步基础
- linux中实现线程同步的6种方法
- 3-多线程安全问题,线程同步
- 多线程(四)-线程同步
- 扫地机器人地图与用户终端的同步
- 6种不同画法画平行线_9.2 平行线和它的画法(练习)-2019-2020学年七年级数学下册同步精品课堂(青岛版)…[通俗易懂]
- DataX数据同步实战案例
- 同步与异步电路信号交互的问题
- 同步异步阻塞非阻塞详解
- 同步优雅的同步:Linux 2.6线程技术(linux2.6线程)
- 轻松实现Linux文件同步:学会使用SCP命令(linuxscp同步)
- Linux下实现多线程操作的同步和互斥机制(linux线程同步与互斥)
- Linux多线程解决同步问题(linux线程同步方式)
- Linux线程同步:多种方案策略(linux线程同步的方法)
- 【解决Linux时间同步关闭问题】(linux时间同步关闭)
- 探究Linux内核同步机制:保证系统稳定性的重要步骤(linux内核的同步)
- 如何监控 MySQL 主从同步?25字(mysql主从监控)
- MSSQL远程更新数据:轻松实现跨平台数据同步(mssql远程更新数据)
- 解析同步两个MySQL表格的SQL操作(mysql两表同步sql)
- 利用Redis实现线程同步(线程里面用redis)
- 重新同步让Redis更加强大(redis重新同步数据)
- 基于Redis实现远端服务器间数据同步(redis连服务器)
- Oracle DSG同步实现数据库一致性(oracle dsg同步)
- 如何做到多笔资料的同步
- 无需密码通过ssh执行rsync来同步文件的方法