【多线程篇】sleep和wait的区别?notify和notify的作用?如何实现生产者 | 您所在的位置:网站首页 › 亚特兰蒂斯古城图片 › 【多线程篇】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 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 实验室设备网 版权所有 |