生产者和消费者之间的线程通讯wait()
生产者与消费者,采用notify()唤醒
package com.dwz.concurrency.chapter9;
/**
* 生产者和消费者之间的通信问题
* 执行wait()之后锁被释放
*/
public class ProduceConsumerVersion4 {
private final Object LOCK = new Object();
private int i = 0;
private volatile boolean isProduced = false; private void produce() {
synchronized(LOCK) {
if(isProduced) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
i++;
System.out.println("p->" + i);
LOCK.notify();
isProduced = true;
}
}
} private void consumer() {
synchronized(LOCK) {
if(isProduced) {
System.out.println("c->" + i);
LOCK.notify();
isProduced = false;
} else {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试代码(一个生产者与一个消费者)
public static void main(String[] args) {
ProduceConsumerVersion4 pc = new ProduceConsumerVersion4();
new Thread("P") {
@Override
public void run() {
while(true) {
pc.produce();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
new Thread("C") {
@Override
public void run() {
while(true) {
pc.consumer();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
测试结果是线程安全的,程序正常结束
测试代码(多个生产者与多个消费者)
public static void main(String[] args) {
ProduceConsumerVersion2 pc = new ProduceConsumerVersion2();
Stream.of("P1", "P2").forEach(n ->
new Thread(n) {
@Override
public void run() {
while(true) {
pc.produce();
}
}
}.start()
);
Stream.of("C1", "C2").forEach(n ->
new Thread(n) {
@Override
public void run() {
while(true) {
pc.consumer();
}
}
}.start()
);
}
测试结果:程序不能正常结束,被阻塞
多个生产者和多个消费者之间通信采用 notify()
缺点:会存在所有线程都等待的问题(wait)
分析:notify不能识别wait的身份,有可能消费者唤醒的是消费者,导致线程都blocked
改进方法,使用notifyAll()代替notify()
package com.dwz.concurrency.chapter9; import java.util.stream.Stream; /**
* 多个生产者和多个消费者之间通信(线程安全版)
*/
public class ProduceConsumerVersion3 {
private final Object LOCK = new Object();
private int i = 0;
private volatile boolean isProducted = false; private void produce() {
synchronized(LOCK) {
if(isProducted) {
try {
LOCK.wait();
return;
} catch (InterruptedException e) {
e.printStackTrace();
}
} i++;
System.out.println(Thread.currentThread().getName() + "for P->" + i);
LOCK.notifyAll();
isProducted = true;
}
} private void consumer() {
synchronized(LOCK) {
if(!isProducted) {
try {
LOCK.wait();
return;
} catch (InterruptedException e) {
e.printStackTrace();
}
} System.out.println(Thread.currentThread().getName() + "for C->" + i);
LOCK.notifyAll();
isProducted = false;
}
}
}
测试结果,程序是线程安全的,正常执行
The difference of sleep and wait
1.sleep is the method of Thread, but wait is the method of Object
2.sleep will not release the object monitor(Lock), but the wait will be release the monitor and add to the Object monitor waiting queue
3.use sleep not need depend on monitor, but wait need
4.The sleep method not need be wakeup, but wait method need.(besides wait(milons))
生产者和消费者之间的线程通讯wait()的更多相关文章
- JAVA之旅(十五)——多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止
JAVA之旅(十五)--多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止 我们接着多线程讲 一.生产者和消费者 什么是生产者和消费者?我们 ...
- JAVA笔记14__多线程共享数据(同步)/ 线程死锁 / 生产者与消费者应用案例 / 线程池
/** * 多线程共享数据 * 线程同步:多个线程在同一个时间段只能有一个线程执行其指定代码,其他线程要等待此线程完成之后才可以继续执行. * 多线程共享数据的安全问题,使用同步解决. * 线程同步两 ...
- 生产者与消费者+Queue(线程安全)
from queue import Queue from lxml import etree import requests from urllib import request from threa ...
- 多进程(了解):守护进程,互斥锁,信号量,进程Queue与线程queue(生产者与消费者模型)
一.守护进程 主进程创建守护进程,守护进程的主要的特征为:①守护进程会在主进程代码执行结束时立即终止:②守护进程内无法继续再开子进程,否则会抛出异常. 实例: from multiprocessing ...
- java 线程并发(生产者、消费者模式)
线程并发协作(生产者/消费者模式) 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型“生产者/消费者模式”. Ø 什么是生产者? 生产者指的是负责生产数 ...
- 线程操作案例--生产者与消费者,Object类对线程的支持
本章目标 1)加深对线程同步的理解 2)了解Object类中对线程的支持方法. 实例 生产者不断生产,消费者不断消费产品. 生产者生产信息后将其放到一个区域中,之后消费者从区域中取出数据. 既然生产的 ...
- python queue和生产者和消费者模型
queue队列 当必须安全地在多个线程之间交换信息时,队列在线程编程中特别有用. class queue.Queue(maxsize=0) #先入先出 class queue.LifoQueue(ma ...
- 守护进程,互斥锁,IPC,生产者与消费者模型
守护进程: b 进程守护 a进程,当a进程执行完毕时,b进程会跟着立马结束 守护进程用途: 如果父进程结束了,子进程无需运行了,就可以将子进程设置为父进程的守护进程 例如我们qq视频聊天时,当我们退出 ...
- go语言实现"生产者"和"消费者"的例子
学习java的多线程的时候最经典的一个例子就是生产者消费者模型的例子,最近在研究go语言协程,发现go提供的sync包中有很多和java类似的锁工具,尝试着用锁工具配合协程实现一个"消费者& ...
随机推荐
- IOC之MEF学习
MEF原理上很简单,找出有共同接口的导入.导出.然后找到把导出的实例化,赋给导入.说到底MEF就是找到合适的类实例化,把它交给导入.Export 特性可修饰类.字段.属性或方法,而 Import 特性 ...
- luogu1313计算系数题解--二项式定理
题目链接 https://www.luogu.org/problemnew/show/P1313 分析 二项式定理 \((a+b)^n=\sum_{k=0}^{n}{C^k_n a^k b^{n-k} ...
- JDK + Tomcat 安装 + 制作自定义镜像【第 3 篇 系统镜像】
[第 1 篇 JDK]:https://www.cnblogs.com/del88/p/11842387.html[第 2 篇 Tomcat]:https://www.cnblogs.com/del8 ...
- oracle中查询表中的触发器,关闭启用操作
1.查询指定表中有哪些触发器 select * from all_triggers WHERE table_name='表名' 2.禁用指定表中所有的触发器 alter table table_nam ...
- navigateTo防止多次跳转
“wx.navigateTo” 页面跳转.在有网络延迟时多次点击会产生 多次二级页面 再使用wx.navigateBack就会多次返回到之前那页面 解决办法: 点击之前标个状态true 点击之后跳转路 ...
- CompletionService异步非阻塞获取并行任务执行结果
第1部分 问题引入 <Java并发编程实践>一书6.3.5节CompletionService:Executor和BlockingQueue,有这样一段话: "如果向Execut ...
- 第六章、ajax方法以及序列化组件
目录 第六章.ajax方法 一.choice参数介绍 二.MTV与MVC模型 三.ajax方法 四.案例 五.Ajax传json格式的数据 六. AJAX传文件 代码如下 ajax传文件需要注意的事项 ...
- 利用Pycharm部署同步更新Django项目文件
利用Pycharm部署同步更新Django项目文件 这里使用同步更新的前提是你已经在服务器上上传了你的Django项目文件. 在"工具(Tools)"菜单中找到"部署(D ...
- golang结构体json格式化的时间格式
golang结构体json格式化的时间格式 在我们开发中,经常会解析time.Time 往往前台传过来的时候,是个string 但是我们希望在结构体转成time.Time type Param str ...
- linux——目录说明
1) bin -> usr/bin : 这个目录存放最经常使用的命令 2) boot : 这个目录存放启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件 3) dev: de ...