【多线程篇】sleep和wait的区别?notify和notify的作用?如何实现生产者 您所在的位置:网站首页 亚特兰蒂斯古城图片 【多线程篇】sleep和wait的区别?notify和notify的作用?如何实现生产者

【多线程篇】sleep和wait的区别?notify和notify的作用?如何实现生产者

#【多线程篇】sleep和wait的区别?notify和notify的作用?如何实现生产者| 来源: 网络整理| 查看: 265

目录 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 container; public static final int MAX_CAPACITY = 5; public Producer(List 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(); } } @Override public void run() { while (true) { try { produce(); } catch (InterruptedException e) { e.printStackTrace(); } } } } 1. 消费者 public class Consumer implements Runnable{ private List container; public Consumer(List 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(); } } @Override public void run() { while (true){ try { consume(); } catch (InterruptedException e) { e.printStackTrace(); } } } } 3. 生产者消费者测试 public class ProducerConsumerTest { public static void main(String[] args) { List 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修饰的,代表是本地库接口,原理是其他语言实现的,我也不清楚



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有