首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >java线程与cpu线程_坑惨了什么意思

java线程与cpu线程_坑惨了什么意思

作者头像
全栈程序员站长
发布2022-10-03 15:06:20
发布2022-10-03 15:06:20
6960
举报

大家好,又见面了,我是你们的朋友全栈君。

在java中,线程间的通信可以使用wait、notify、notifyAll来进行控制。从名字就可以看出来这3个方法都是跟多线程相关的,但是可能让你感到吃惊的是:这3个方法并不是Thread类或者是Runnable接口的方法,而是Object类的3个本地方法。

其实要理解这一点也并不难,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){…}的内部才能够去调用obj的wait与notify/notifyAll三个方法,否则就会报错:

代码语言:javascript
复制
  java.lang.IllegalMonitorStateException:current thread not owner

也就是说,在调用这3个方法的时候,当前线程必须获得这个对象的锁,那么这3个方法就是和对象锁相关的,所以是属于Object的方法而不是Thread,因为不是每个对象都是Thread。所以我们在理解wait、notify、notifyAll之前,先要了解以下对象锁。

多个线程都持有同一个对象的时候,如果都要进入synchronized(obj){…}的内部,就必须拿到这个对象的锁,synchronized的机制保证了同一时间最多只能有1个线程拿到了对象的锁,如下图:

下面我们来看一下这3个方法的作用:

  • wait:线程自动释放其占有的对象锁,并等待notify
  • notify:唤醒一个正在wait当前对象锁的线程,并让它拿到对象锁
  • notifyAll:唤醒所有正在wait前对象锁的线程

notify和notifyAll的最主要的区别是:notify只是唤醒一个正在wait当前对象锁的线程,而notifyAll唤醒所有。值得注意的是:notify是本地方法,具体唤醒哪一个线程由虚拟机控制;notifyAll后并不是所有的线程都能马上往下执行,它们只是跳出了wait状态,接下来它们还会是竞争对象锁。

下面通过一个常用生产者、消费者的例子来说明。 消息实体类:

代码语言:javascript
复制
package com.podongfeng;

/** * Title: Message.class<br> * Description: 消息实体<br> * Create DateTime: 2016年04月17日 下午1:27 <br> * * @author podongfeng */
public class Message { 
   
}

生产者:

代码语言:javascript
复制
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();
}
}
public Message waitMsg() { 

synchronized(msgList) { 

if(msgList.size() == 0) { 

try { 

msgList.wait();
} catch(InterruptedException e) { 

e.printStackTrace();
}
}
return msgList.remove(0);
}
}
}

消费者:

代码语言:javascript
复制
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;
}
@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();
}
}

消费者线程调用waitMsg去获取一个消息实体,如果msgList为空,则线程进入wait状态;生产这线程每隔3秒钟生产出体格msg实体并放入msgList列表,完成后,调用notify唤醒一个消费者线程去消费。

最后再次提醒注意: wait、notify、notifyAll并不是Thread类或者是Runnable接口的方法,而是Object类的3个本地方法。 在调用这3个方法的时候,当前线程必须获得这个对象的锁

最后的惯例:点个小赞,好运不断,来个关注,青春常驻,打个小赏,工资疯涨。。。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/197342.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月4日 下,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档