目录

  • 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. 使用场景

  1. 生产者-消费者模式

3. notify

1. notify的作用

  1. 等待池中的线程转移到锁池中(锁池中的线程会去积极地抢锁)
  2. notify方法不释放锁,要等方法执行完毕之后才会释放锁

2. 为什么要使用notify、notifyAll?

因为要提醒其他线程,从等待池锁池

例如:
线程A调用wait方法之后,会进入等待池线程A会把这个锁释放,供其他线程抢,线程B抢到这个锁,并跑完程序,想要释放这个锁给线程A用,但是线程A还在等待池中,这时候就必须要使用notifynotifyAll方法,把线程A叫到锁池

白话文:(占有锁的线程)用完(线程运行完毕,且释放锁)要告诉我们(notify或notifyAll)一声,不然我们(其他线程)是不会从休息区(等待池)到战斗区(锁池)去厮杀(抢锁)

3. 应用场景

  1. 生产者-消费者模式

4. 如何使用wait和notifyAll实现生产者-消费者模式

1. 注意事项

  1. 使用waitnotify可以实现线程间的通信(多个线程可以使用这些方法相互通信)
  2. 必须获得锁才能使用这些方法,如synchronizedsynchronized块里使用
  3. while代替if做条件判断
  4. 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的作用?如何实现生产者-消费者模式相关推荐

  1. 菜鸟学习笔记:Java提升篇8(线程2——线程的基本信息、线程安全、死锁、生产者消费者模式、任务调度)

    菜鸟学习笔记:Java提升篇8(线程2--线程的基本信息.线程安全.死锁.生产者消费者模式.任务调度) 线程的基本信息 线程同步 线程安全 死锁 生产者消费者模式 任务调度(了解) 线程的基本信息 J ...

  2. 【C++】多线程(链式、循环队列)实现生产者消费者模式

    生产者消费者模式:         生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同 ...

  3. 多线程终极模式:生产者-消费者模式

    多线程de小事情 导航不迷路: 程序.进程以及线程的爱恨情仇 最简单实现多线程的方法(Thread) 简单易懂的多线程(通过实现Runnable接口实现多线程) 常用获取线程基本信息的方法(新手专属) ...

  4. 单线程下的生产者--消费者模式详解,wait和sleep的区别

    1. 单线程下的生产者--消费者模式 1.1 该模式下,一个线程生产数据,另一个线程处理数据.当数据还没被处理,那么生产数据的线程进入等待状态:如果数据还没生产,那么处理数据的线程进入等待状态,代码及 ...

  5. Java多线程学习三:有哪几种实现生产者消费者模式的方法

    我们先来看看什么是生产者消费者模式,生产者消费者模式是程序设计中非常常见的一种设计模式,被广泛运用在解耦.消息队列等场景.在现实世界中,我们把生产商品的一方称为生产者,把消费商品的一方称为消费者,有时 ...

  6. 生产者消费者模式与订阅发布者模式的区别

    订阅发布者模式本质上也是一种生产者消费者模式,订阅者是消费者,发布者是生产者.如果一定要说个区别,就是抽象级别的区别吧. 订阅者肯定是个消费者,但消费者不一定是订阅者,发布者一定是个生产者,但生产者不 ...

  7. 使用wait()和notify()方法实现生产者消费者模式

    以下总结只是个人理解,如有错误,敬请指正. 一.wait()和notify()作用 wait()和notify()方法是Object类的方法,因为Object类是所有类的根类,因此所有类都有这两个方法 ...

  8. [19/04/11-星期四] 多线程_并发协作(生产者/消费者模式_2种解决方案(管程法和信号灯法))...

    一.概念 多线程环境下,我们经常需要多个线程的并发和协作.这个时候,就需要了解一个重要的多线程并发协作模型"生产者/消费者模式". Ø 什么是生产者? 生产者指的是负责生产数据的模 ...

  9. java消费者生产者设计模式_java 多线程并发设计模式之四: 生产者消费者模式

    生产者消费者模式是一个经典的多线程设计模式,其核心思想是:有两类线程和一个内存缓冲区或者队列, 一类线程发起任务,并提交到队列中.另一类线程用来处理这些任务,叫做消费者线程. 这两类线程进行通信的桥梁 ...

最新文章

  1. mongodb 聚合 分组查询
  2. 后台开发经典书籍--代码大全
  3. 插入排序、选择排序、快速排序以及归并排序(附Python代码)
  4. 评职称不需英语计算机的文件,《关于重申专业技术人员职称评定、职务聘任必须坚持外语、计算机条件的通知》……...
  5. 开源]OSharpNS 步步为营系列 - 1. 业务模块设计
  6. [汇编语言]实验三:栈和栈段
  7. AllTray-将办法最小化到琐细托盘
  8. Express接口案例——完成文章增删改查接口
  9. MySQL:错误代码1215 无法添加外键约束的解决思路
  10. torch.nn.NLLLoss()
  11. 情感分类(Sentiment Classification)
  12. 【windows下基于Eclipse和GCC搭建stm32开发环境(4)】STM32启动过程详解
  13. 首席架构师的领导力和管理能力
  14. 微信可以批量清理僵尸粉啦
  15. 百度AI——人脸识别案例
  16. 二元隐函数求二阶偏导_高数,隐函数求二阶偏导。f(x-y,yz)确定了z=(x,y),f具有二阶连续偏导数,求...
  17. HTTP与HTTPS,HTTPS更加安全。
  18. Windows10安装Centos7双系统
  19. getUserMedia API及HTML5 调用手机摄像头拍照
  20. 会计事务所审计、咨询等项目管理用泛微,数据关联、协作灵活

热门文章

  1. 美颜SDK怎么用?美颜SDK可以应用到哪些场景?
  2. 【opencv学习笔记】003之图像像素基本操作(获取像素指针、范围处理)及掩膜操作(filter2D)详解
  3. 【LeetCode】234. Palindrome Linked List
  4. [RK3568 Android11] 开发之GT911触摸屏调试
  5. 设备接入阿里云物联网平台
  6. 港大计算机系教授中科大毕业的吗,中科大回顾:那些压抑、纠结、煎熬和开心的经历...
  7. KISS原则(keep it simple and stupid)
  8. flash与java交互数据
  9. mysql获取时间戳_mysql 获取当前时间戳
  10. 靠手表“上位”的儿童社交,“红眼”微信做儿童版就有机会了吗?