我被线程坑惨了!线程间的通信有毒!!! 本是古典 何须时尚 2021-07-24 18:25 335阅读 0赞 在java中,线程间的通信可以使`用wait`、`notify`、`notifyAll`来进行控制。从名字就可以看出来这3个方法都是跟多线程相关的,但是可能让你感到吃惊的是:这3个方法并不是Thread类或者是`Runnable`接口的方法,而是Object类的3个本地方法。 其实要理解这一点也并不难,调用一个Object的wait与`notify/notifyAll`的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于`synchronized(obj){......}`的内部才能够去调用obj的wait与`notify/notifyAll`三个方法,否则就会报错: `java.lang.IllegalMonitorStateException:current thread not owner` 也就是说,在调用这3个方法的时候,当前线程必须获得这个对象的锁,那么这3个方法就是和对象锁相关的,所以是属于Object的方法而不是Thread,因为不是每个对象都是Thread。所以我们在理解`wait、notify、notifyAll`之前,先要了解以下对象锁。 多个线程都持有同一个对象的时候,如果都要进入synchronized(obj)\{…\}的内部,就必须拿到这个对象的锁,synchronized的机制保证了同一时间最多只能有1个线程拿到了对象的锁,如下图: ![20210517214013877.png][] 下面我们来看一下这3个方法的作用: * wait:线程自动释放其占有的对象锁,并等待notify * notify:唤醒一个正在wait当前对象锁的线程,并让它拿到对象锁 * notifyAll:唤醒所有正在wait前对象锁的线程 notify和notifyAll的最主要的区别是:notify只是唤醒一个正在wait当前对象锁的线程,而notifyAll唤醒所有。值得注意的是:notify是本地方法,具体唤醒哪一个线程由虚拟机控制;notifyAll后并不是所有的线程都能马上往下执行,它们只是跳出了wait状态,接下来它们还会是竞争对象锁。 下面通过一个常用生产者、消费者的例子来说明。 ## 消息实体类: ## package com.podongfeng; /** * Title: Message.class<br> * Description: 消息实体<br> * Create DateTime: 2016年04月17日 下午1:27 <br> * * @author podongfeng *///加入Java开发交流君样:756584822一起吹水聊天 public class Message { } ## 生产者: ## package com.podongfeng; import java.util.ArrayList; import java.util.List; /** * Title: Producer.class<br> * Description: 消息生产者<br> * Create DateTime: 2016年04月17日 下午1:28 <br> * * @author podongfeng */ public class Producer extends Thread { List<Message> msgList = new ArrayList<>(); @Override public void run() { try { while (true) { Thread.sleep(3000); Message msg = new Message(); synchronized(msgList) { msgList.add(msg); msgList.notify(); //这里只能是notify而不能是notifyAll,否则remove(0)会报java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 } } } catch (Exception e) { e.printStackTrace(); } }//加入Java开发交流君样:756584822一起吹水聊天 public Message waitMsg() { synchronized(msgList) { if(msgList.size() == 0) { try { msgList.wait(); } catch(InterruptedException e) { e.printStackTrace(); } } return msgList.remove(0); } }//加入Java开发交流君样:756584822一起吹水聊天 } ## 消费者: ## package com.podongfeng; /** * Title: Consumer.class<br> * Description: 消息消费者<br> * Create DateTime: 2016年04月17日 下午1:28 <br> * * @author podongfeng */ public class Consumer extends Thread { private Producer producer; public Consumer(String name, Producer producer) { super(name); this.producer = producer; } //加入Java开发交流君样:756584822一起吹水聊天 @Override public void run() { while (true) { Message msg = producer.waitMsg(); System.out.println("Consumer " + getName() + " get a msg"); } } public static void main(String[] args) { Producer p = new Producer(); p.start(); new Consumer("Consumer1", p).start(); new Consumer("Consumer2", p).start(); new Consumer("Consumer3", p).start(); } }//加入Java开发交流君样:756584822一起吹水聊天 消费者线程调用waitMsg去获取一个消息实体,如果msgList为空,则线程进入wait状态;生产这线程每隔3秒钟生产出体格msg实体并放入msgList列表,完成后,调用notify唤醒一个消费者线程去消费。 **最后再次提醒注意:** wait、notify、notifyAll并不是Thread类或者是Runnable接口的方法,而是Object类的3个本地方法。 在调用这3个方法的时候,当前线程必须获得这个对象的锁 生命不止坚毅鱼奋斗,有梦想才是有意义的追求 给大家推荐一个免费的学习交流群: 最后,祝大家早日学有所成,拿到满意offer,快速升职加薪,走上人生巅峰。 [Java开发交流君样:756584822][Java_756584822] [20210517214013877.png]: /images/20210724/fc2828d4ad224b00aa2a03e429379b25.png [Java_756584822]: https://jq.qq.com/?_wv=1027&k=0IsBuUb0
相关 单线程间通信 多线程间通信 单线程间通信 <table> <thead> <tr> <th align="left">首先实现一个EventQueue,该Queue有如下三种状 朱雀/ 2024年03月16日 11:51/ 0 赞/ 67 阅读
相关 线程间通信 为什么需要线程通讯 线程是操作系统调度的最小单位,有自己的栈空间,可以按照既定的代码逐步的执行,但是如果每个线程间都孤立的运行,那就会造资源浪费。所以在现实中,我们需要这 心已赠人/ 2022年09月08日 00:12/ 0 赞/ 277 阅读
相关 线程间的通信 https://www.cnblogs.com/hapjin/p/5492619.html 通常可用把并行程序理解为一组相互独立的、能够发关和接收消息的组件,这也称为角 朱雀/ 2022年05月17日 03:00/ 0 赞/ 151 阅读
相关 线程间通信 线程和线程之间不是独立的个体,它们彼此之间可以互相通信和协作。 线程通信就是在线程之间传递信息,保证他们能够协同工作。在线程间进行通信后,系统之间的交互性会更强大,在大大提高 Myth丶恋晨/ 2022年05月17日 01:36/ 0 赞/ 286 阅读
相关 线程间通信 一、引言 线程与线程之间不是相互独立的存在,它们彼此之间需要相互通信和协作。最典型的例子就是生产者-消费者问题。下面首先介绍 wait/notify 机制,并对实现该机制 墨蓝/ 2022年04月11日 13:56/ 0 赞/ 313 阅读
相关 线程间通信 注意: 必须在同步方法中使用wait和notify方法,因为执行wait和notify的前提条件是必须持有同步方法(或块)的monitor的所有权,否则将会抛出异常 女爷i/ 2022年02月28日 09:33/ 0 赞/ 394 阅读
相关 线程间的通信 典型例子就是生产者-消费者模式,仓库为空时,消费者无法从仓库调动产品,只能wait,直到仓库有产品时被notify;仓库满了时,生产者则暂时停止生产(wait),直到仓库有空被 喜欢ヅ旅行/ 2022年01月29日 10:34/ 0 赞/ 272 阅读
相关 线程间通信 一、线程间通信 1. 需要三个重要的方法:(java.lang.Object包下) 三种方法使用之前一定要加锁 ①wait() ②n 缺乏、安全感/ 2021年09月28日 14:14/ 0 赞/ 398 阅读
相关 我被线程坑惨了!线程间的通信有毒!!! 在java中,线程间的通信可以使`用wait`、`notify`、`notifyAll`来进行控制。从名字就可以看出来这3个方法都是跟多线程相关的,但是可能让你感到吃惊的是:这 本是古典 何须时尚/ 2021年07月24日 18:25/ 0 赞/ 336 阅读
还没有评论,来说两句吧...