【多线程篇】sleep和wait的区别?notify和notify的作用?如何实现生产者-消费者模式
目录
- sleep和wait的区别?
- 1. sleep方法(休眠)
- 1. 源码分析
- 2. 作用
- 3. 题外话:sleep之后线程会释放锁吗
- 4. sleep的使用场景
- 2. wait方法(等待)
- 1. 源码分析
- 1. 作用
- 2. 使用场景
- 3. notify
- 1. notify的作用
- 2. 为什么要使用notify、notifyAll?
- 3. 应用场景
- 4. 如何使用wait和notifyAll实现生产者-消费者模式
- 1. 注意事项
- 1. 题外话:为什么wait和notify方法要在synchronized方法里使用?
- 2. 实现
- 1. 生产者
- 1. 消费者
- 3. 生产者消费者测试
- 4. 控制台现象
- 1. 控制台现象分析
- 2. 问:为什么会一直循环下去?start启动一个线程之后,不会关闭吗?
- 5. 为什么wait方法可以释放对象的锁,而sleep不行?
- 6. sleep线程是怎么让出CPU的?原理是什么
sleep和wait的区别?
1. sleep方法(休眠)
1. 源码分析
class Thread implements Runnable {public static native void sleep(long millis) throws InterruptedException;
}
sleep方法是Thread类的实例方法,且这个方法被native修饰,是一个本地库接口
2. 作用
让线程进入阻塞状态,并主动让出CPU,但还会占有锁
3. 题外话:sleep之后线程会释放锁吗
不会,sleep方法只对CPU操作,并不会去操作对象的锁(tips:对象锁的状态是保存在对象头的,这个在【八股文】JVM篇有讲
4. sleep的使用场景
高优先级线程因为一些原因(自身操作比较耗时、需要低优先级线程的数据),需要让低优先级线程先执行,可以自己调用sleep操作,让出CPU
2. wait方法(等待)
1. 源码分析
public class Object {public final void wait() throws InterruptedException {wait(0);}public final native void wait(long timeout) throws InterruptedException;}
wait方法是Object对象类的实例方法,是对象的方法,其本质也是用native修饰的,是一个本地库方法
1. 作用
自己进入等待池,暂时(暂时体现在哪里?和sleep区别?)让出CPU的使用权,也会释放同步锁
白话文:中断线程的运行(中断恢复之后会回到原来的位置wait方法,还是会到获取锁的位置),让出CPU,让出同步锁
2. 使用场景
- 生产者-消费者模式
3. notify
1. notify的作用
- 让等待池中的线程转移到锁池中(锁池中的线程会去积极地抢锁)
- notify方法不释放锁,要等方法执行完毕之后才会释放锁
2. 为什么要使用notify、notifyAll?
因为要提醒其他线程,从等待池到锁池
例如:
线程A调用wait方法之后,会进入等待池,线程A会把这个锁释放,供其他线程抢,线程B抢到这个锁,并跑完程序,想要释放这个锁给线程A用,但是线程A还在等待池中,这时候就必须要使用notify或notifyAll方法,把线程A叫到锁池里
白话文:你(占有锁的线程)用完(线程运行完毕,且释放锁)要告诉我们(notify或notifyAll)一声,不然我们(其他线程)是不会从休息区(等待池)到战斗区(锁池)去厮杀(抢锁)
3. 应用场景
- 生产者-消费者模式
4. 如何使用wait和notifyAll实现生产者-消费者模式
1. 注意事项
- 使用wait和notify可以实现线程间的通信(多个线程可以使用这些方法相互通信)
- 必须获得锁才能使用这些方法,如synchronized或synchronized块里使用
- 用while代替if做条件判断
- 用notifyAll代替notify
1. 题外话:为什么wait和notify方法要在synchronized方法里使用?
synchronized的语义底层是通过一个monitor的对象来完成,其实wait、notify等方法也依赖于monitor对象,否则会抛出java.lang.IllegalMonitorStateException的异常(不合法的监视器状态)
2. 实现
1. 生产者
public class Producer implements Runnable {private final List<Integer> container;public static final int MAX_CAPACITY = 5;public Producer(List<Integer> container) {this.container = container;}private void produce() throws InterruptedException {synchronized (container) {while (container.size() == MAX_CAPACITY) {System.out.println("容器已满,暂停生产");container.wait();}int p = RandomUtils.nextInt();System.out.println("生产产品:" + p);container.add(p);container.notifyAll();}}@Overridepublic void run() {while (true) {try {produce();} catch (InterruptedException e) {e.printStackTrace();}}}
}
1. 消费者
public class Consumer implements Runnable{private List<Integer> container;public Consumer(List<Integer> container) {this.container = container;}private void consume() throws InterruptedException {synchronized (container){while (container.isEmpty()){System.out.println("容器已空,暂停消费");container.wait();}Integer p = container.remove(0);TimeUnit.MILLISECONDS.sleep(1000);System.out.println("消费产品:" + p);container.notifyAll();}}@Overridepublic void run() {while (true){try {consume();} catch (InterruptedException e) {e.printStackTrace();}}}
}
3. 生产者消费者测试
public class ProducerConsumerTest {public static void main(String[] args) {List<Integer> container = new ArrayList<>();Thread producer = new Thread(new Producer(container));Thread consumer = new Thread(new Consumer(container));producer.start();consumer.start();}
}
4. 控制台现象
Connected to the target VM, address: '127.0.0.1:54861', transport: 'socket'
容器已空,暂停消费
生产产品:1539478251
生产产品:2055287902
生产产品:244175613
生产产品:836101091
生产产品:346467918
容器已满,暂停生产
消费产品:1539478251
消费产品:2055287902
消费产品:244175613
消费产品:836101091
消费产品:346467918
容器已空,暂停消费
生产产品:2056187818
生产产品:1148572189
生产产品:1951629848
生产产品:767221295
生产产品:2009198874
容器已满,暂停生产
1. 控制台现象分析
消费者发现容器为空,调用wait方法直接去等待池,生产者开始生产数据,生产者满了将调用wait,并notifyAll其他线程,消费者被唤醒,开始消费数据。。。如此往复执行。。
2. 问:为什么会一直循环下去?start启动一个线程之后,不会关闭吗?
如果代码运行完毕的话,是会关闭线程的,一直循环说明进入了while,编不下去了。。TODO搞不清,不太理解
5. 为什么wait方法可以释放对象的锁,而sleep不行?
- wait方法是Object的方法(对象的方法),那就代表着wait方法可以控制对象相关的一些属性,比如对象头中的一些属性(如对象锁的状态、持有锁的线程名),所以wait方法可以释放对象的锁
- sleep方法是Thread的方法,不能控制对象相关的操作,也就不能控制锁的释放了
6. sleep线程是怎么让出CPU的?原理是什么
sleep方法是native修饰的,代表是本地库接口,原理是其他语言实现的,我也不清楚
【多线程篇】sleep和wait的区别?notify和notify的作用?如何实现生产者-消费者模式相关推荐
- 菜鸟学习笔记:Java提升篇8(线程2——线程的基本信息、线程安全、死锁、生产者消费者模式、任务调度)
菜鸟学习笔记:Java提升篇8(线程2--线程的基本信息.线程安全.死锁.生产者消费者模式.任务调度) 线程的基本信息 线程同步 线程安全 死锁 生产者消费者模式 任务调度(了解) 线程的基本信息 J ...
- 【C++】多线程(链式、循环队列)实现生产者消费者模式
生产者消费者模式: 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同 ...
- 多线程终极模式:生产者-消费者模式
多线程de小事情 导航不迷路: 程序.进程以及线程的爱恨情仇 最简单实现多线程的方法(Thread) 简单易懂的多线程(通过实现Runnable接口实现多线程) 常用获取线程基本信息的方法(新手专属) ...
- 单线程下的生产者--消费者模式详解,wait和sleep的区别
1. 单线程下的生产者--消费者模式 1.1 该模式下,一个线程生产数据,另一个线程处理数据.当数据还没被处理,那么生产数据的线程进入等待状态:如果数据还没生产,那么处理数据的线程进入等待状态,代码及 ...
- Java多线程学习三:有哪几种实现生产者消费者模式的方法
我们先来看看什么是生产者消费者模式,生产者消费者模式是程序设计中非常常见的一种设计模式,被广泛运用在解耦.消息队列等场景.在现实世界中,我们把生产商品的一方称为生产者,把消费商品的一方称为消费者,有时 ...
- 生产者消费者模式与订阅发布者模式的区别
订阅发布者模式本质上也是一种生产者消费者模式,订阅者是消费者,发布者是生产者.如果一定要说个区别,就是抽象级别的区别吧. 订阅者肯定是个消费者,但消费者不一定是订阅者,发布者一定是个生产者,但生产者不 ...
- 使用wait()和notify()方法实现生产者消费者模式
以下总结只是个人理解,如有错误,敬请指正. 一.wait()和notify()作用 wait()和notify()方法是Object类的方法,因为Object类是所有类的根类,因此所有类都有这两个方法 ...
- [19/04/11-星期四] 多线程_并发协作(生产者/消费者模式_2种解决方案(管程法和信号灯法))...
一.概念 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型"生产者/消费者模式". Ø 什么是生产者? 生产者指的是负责生产数据的模 ...
- java消费者生产者设计模式_java 多线程并发设计模式之四: 生产者消费者模式
生产者消费者模式是一个经典的多线程设计模式,其核心思想是:有两类线程和一个内存缓冲区或者队列, 一类线程发起任务,并提交到队列中.另一类线程用来处理这些任务,叫做消费者线程. 这两类线程进行通信的桥梁 ...
最新文章
- mongodb 聚合 分组查询
- 后台开发经典书籍--代码大全
- 插入排序、选择排序、快速排序以及归并排序(附Python代码)
- 评职称不需英语计算机的文件,《关于重申专业技术人员职称评定、职务聘任必须坚持外语、计算机条件的通知》……...
- 开源]OSharpNS 步步为营系列 - 1. 业务模块设计
- [汇编语言]实验三:栈和栈段
- AllTray-将办法最小化到琐细托盘
- Express接口案例——完成文章增删改查接口
- MySQL:错误代码1215 无法添加外键约束的解决思路
- torch.nn.NLLLoss()
- 情感分类(Sentiment Classification)
- 【windows下基于Eclipse和GCC搭建stm32开发环境(4)】STM32启动过程详解
- 首席架构师的领导力和管理能力
- 微信可以批量清理僵尸粉啦
- 百度AI——人脸识别案例
- 二元隐函数求二阶偏导_高数,隐函数求二阶偏导。f(x-y,yz)确定了z=(x,y),f具有二阶连续偏导数,求...
- HTTP与HTTPS,HTTPS更加安全。
- Windows10安装Centos7双系统
- getUserMedia API及HTML5 调用手机摄像头拍照
- 会计事务所审计、咨询等项目管理用泛微,数据关联、协作灵活
热门文章
- 美颜SDK怎么用?美颜SDK可以应用到哪些场景?
- 【opencv学习笔记】003之图像像素基本操作(获取像素指针、范围处理)及掩膜操作(filter2D)详解
- 【LeetCode】234. Palindrome Linked List
- [RK3568 Android11] 开发之GT911触摸屏调试
- 设备接入阿里云物联网平台
- 港大计算机系教授中科大毕业的吗,中科大回顾:那些压抑、纠结、煎熬和开心的经历...
- KISS原则(keep it simple and stupid)
- flash与java交互数据
- mysql获取时间戳_mysql 获取当前时间戳
- 靠手表“上位”的儿童社交,“红眼”微信做儿童版就有机会了吗?