Java学习day26:和线程相关的Object类的方法、等待线程和唤醒线程(知识点详解)

声明:该专栏本人重新过一遍java知识点时候的笔记汇总,主要是每天的知识点+题解,算是让自己巩固复习,也希望能给初学的朋友们一点帮助,大佬们不喜勿喷(抱拳了老铁!)


往期回顾

Java学习day25:守护线程、死锁、线程生命周期(知识点详解)-CSDN博客

Java学习day24:线程的同步和锁(例题+知识点详解)-CSDN博客

Java学习day23:线程构造方法、常用方法(例题+知识点详解)-CSDN博客

 Java学习day26:和线程相关的Object类下面的方法、等待线程和唤醒线程

一、和线程相关的Object类的方法

1.三个常用方法

void wait()  导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
void notify()  唤醒正在等待对象监视器的单个线程。
void notifyAll() 唤醒正在等待对象监视器的所有线程。

wait()  方法换句话说,这个方法的行为就好像简单地执行呼叫`wait(0)`

二、等待线程和唤醒线程

1.什么是等待线程和唤醒线程

上面我们看了,Object类的三个主要方法,这三个主要方法就涉及到等待线程和唤醒线程,也就是说,至少两个线程,其中一个线程中使用对象.wait()  那么这个线程就会阻塞,代码不会往下执行了。也就是我们说的,等待线程。如何想让这个线程往下执行呢?再开另外一个线程,使用对象.notify()去唤醒另外那个等待线程。也就是我们说的唤醒线程,如果多个等待线程,一个唤醒线程,则调用notifyAll()方法,就能一次性唤醒所有等待线程。

我们用代码来理解

示例:

//创建这个类的目的,就是实例化出来对象,然后拿这个对象
//调用wait方法和notify方法
//wait方法和notify方法是object对象的方法
class Message {private String message;public Message(String message) {this.message = message;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}@Overridepublic String toString() {return "Message{" +"message='" + message + '\'' +'}';}}
//导致当前线程等待,直到另一个线程调用该对象的[`notify()`
class WaiterThread implements Runnable {//想一个问题?WaiterThread  使用message对象调用//wait() 咋解决?private Message msg;public WaiterThread(Message msg) {this.msg = msg;}@Overridepublic void run() {//先获取当前线程名字String name = Thread.currentThread().getName();System.out.println(name + "等待唤醒时间:" +System.currentTimeMillis());//让等待线程去阻塞,去等待  这个线程执行不下去了//锁的是msg对象synchronized (msg) {//为啥用这个wait的时候要加锁?等会讲try {msg.wait();//代码走到这,当前这个线程阻塞,不往下走了//咱们得想办法让这个等待线程继续执行下去,咋办?//在另外一个线程中去调用notify方法那么等待线程就会执行下去} catch (InterruptedException e) {e.printStackTrace();}System.out.println("123");System.out.println(name + "被唤醒的时间:" + System.currentTimeMillis());}}
}
//唤醒线程
class NotifyThread implements Runnable {//也要用同一个对象是WaiterThread线程中同一个对象调用notify()方法private Message msg;public NotifyThread(Message msg) {this.msg = msg;}@Overridepublic void run() {try {//我的想法是不能先让唤醒线程执行Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}String name = Thread.currentThread().getName();System.out.println(name + "开始唤醒等待线程");synchronized (msg) {msg.setMessage("我是修改之后的message值");msg.notify();//msg.notifyAll();//唤醒所有线程}}
}
public class Demo1 {public static void main(String[] args) {Message message = new Message("我是message属性");WaiterThread waiterThread = new WaiterThread(message);NotifyThread notifyThread = new NotifyThread(message);//如果等待线程好几个 咋办呢?new Thread(waiterThread, "等待线程1").start();// new Thread(waiterThread, "等待线程2").start();//new Thread(waiterThread, "等待线程3").start();new Thread(notifyThread, "唤醒线程").start();   }
}

代码执行结果:

        //等待线程等待唤醒时间:1660187660718   等待线程
        //唤醒线程开始唤醒等待线程        唤醒线程
        //123  等待线程
        //等待线程被唤醒的时间:1660187661740  等待线程
        //这叫线程之间的通信问题!!! 

理解这段代码核心:
先是写一个message方法用于信息显示,这个没啥好说的,然后写了两个类用来创建两个线程,分别是等待线程和唤醒线程,等待线程执行wait方法后就相当于不再执行接下来的代码,进入就绪等待状态,让唤醒线程获得cpu使用权,唤醒线程调用notify()方法后,等待线程再继续执行。同时代码里已经写清楚了,如果有多个等待线程,则唤醒线程的对象需要调用notifyAll()方法,一次性唤醒所有等待线程,而且我们必须明确的是,哪个等待线程先被唤醒是不知道的,因为抢占式运行,哪个线程先抢到cpu执行权,唤醒线程就先唤醒哪个线程。

总结:

新建两个线程:
 一个是等待线程
  线程里面的代码从上往下执行的,但是使用object.wait(),就这个方法一用,你的线程就
  阻塞了,就处于等待状态。意味着当前的代码到了wait方法以后的代码暂时不执行了
 另外一个是唤醒线程。
  唤醒线程中使用object.notify()方法,这个方法是专门唤醒刚才那个等待线程。让等待线程继续执行

同时,有一个很重要的点:调用wait()的等待线程必须加锁,具体为什么? 

wait需要持有锁的原因是,你肯定需要知道在哪个对象上进行等待,如果不持有锁,将无法做到对象变更时进行实时感知通知的作用。与此同时,为了让其他线程可以操作该值的变化,它必须要先释放掉锁,然后在该节点上进行等待。不持有锁而进行wait,可能会导致长眠不起。而且,如果不持有锁,则当wait之后的操作,都可能是错的,因为可能这个数据已经过时,其实也叫线程不安全了。总之,一切为了安全,单独的wait做不成这事。

通俗来说就是,因为我要知道对哪个对象进行唤醒的!!!
举个生活中的例子:
 大学的时候在楼底下等过自己的女朋友。
 你就是等待线程
 你女朋友就是唤醒线程
 你在楼底下等的时候  就是在wait。
 你女朋友下楼之后,唤醒你  咱们走吧。
 但是你女朋友 去唤醒别人的男朋友?这就扯犊子了,所有的加锁是为了保证是同一个对象的 

所以说,我们必须要对等待线程和唤醒线程都加锁。 


以上,就是今天的所有知识点了。等待线程和唤醒线程的代码大家要多花点时间理解,方法其实就三个,但是大家要知道怎么用的,有些代码细节都没讲到,大家要自己多花点时间,静下心看代码,写代码,多理解,多运用,重点是多去运用。

加油吧,预祝大家变得更强!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/663380.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

假期刷题打卡--Day20

1、MT1173魔数 一个数字,把他乘以二,会得到一个新的数字,如果这个新数字依然由原数中那些数字组成,就称原数为一个魔数。输入正整数N,检查它是否是一个魔数,输出YES或者NO。 格式 输入格式: …

MySQL之SQL的查询语句如何执行

文章目录 前言一、一条查询的SQL是如何执行的二、MySQL的“零件”们1.连接器2.查询缓存3.分析器4.优化器5.执行器 总结 前言 做了多年技术之后,技术更新换代太快,从我入行时候从单体架构到后面分布式SOA,再到微服务,从后端再到全…

Docker搭建MySQL8主从复制

之前文章我们了解了面试官:说一说Binlog是怎么实现的,这里我们用Docker搭建主从复制环境。 docker安装主从MySQL 这里我们使用MySQL8.0.32版本: 主库配置 master.cnf //基础配置 [client] port3306 socket/var/run/mysqld/mysql.sock [m…

Java项目:基于SSM框架实现的教务管理系统(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm813基于SSM框架实现的教务管理系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#x…

Docker进阶篇-DockerFile

一、简介 Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚 本。 构建步骤: 1、编写Dockerfile文件 2、docker build命令构建镜像 3、docker run依镜像运行容器实例 二、Docker构建过程解析 1、Dockerfile…

2024美国大学生数学建模C题网球运动中的势头详解思路+具体代码

2024美国大学生数学建模C题网球运动中的势头详解思路具体代码 E题数据已更新,做E题的小伙伴推荐看看博主的E题解析文章。那么废话不多说我们继续来做C题。 赛题分析 我们先阅题: 在2023年温布尔登男单决赛中,20岁的西班牙新星卡洛斯阿尔卡…

数据结构—动态查找

动态查找介绍 1. 动态查找的引入:当查找表以线性表的形式组织时,若对查找表进行插入、删除或排序操作,就必须移动大量的记录,当记录数很多时,这种移动的代价很大。 2. 动态查找表的设计思想:表结构本身是…

【论文速览_01】Awesome Few Shot Segmentation论文

Awesome Few Shot Segmentation Awesome Few Shot Segmentation论文CVPR 2023Hierarchical Dense Correlation Distillation for Few-Shot Segmentation文章内容 MIANet: Aggregating Unbiased Instance and General Information for Few-Shot Semantic Segmentation文章内容 I…

探讨深浅拷贝在js加密中的运用

深浅拷贝是JavaScript中常用的概念,用于复制对象或数组。它们在处理数据时有不同的用途,适用于不同的场景。在本文中,我们将详细介绍深浅拷贝的概念,提供案例代码,并探讨它们在JavaScript中的应用场景,以及…

MySQL原理(一)架构组成之逻辑模块(1)组成

总的来说,MySQL可以看成是二层架构,第一层我们通常叫做SQL Layer,在MySQL数据库系统处理底层数据之前的所有工作都是在这一层完成的,包括权限判断,sql解析,执行计划优化,query cache的处理等等&…

中二少年工具箱(PC端)简介

同学们可以私信我加入学习群! 正文开始 简介一、功能模块1.node版本管理工具 总结 简介 中二少年开发的中二少年工具箱,相信博主,功能不孬。 辅助自己开发工作,帮助新人快速入门,提供交互式文档辅助学习……如果还不…

拓展欧几里得法求逆元

板子: x即为最终答案,x可能为负数,加模数即可 乘法逆元 - OI Wiki (oi-wiki.org) void exgcd(int a, int b, int& x, int& y) {if (b 0) {x 1, y 0;return;}exgcd(b, a % b, y, x);y - a / b * x; } 使用: exgcd(a, n 1, x,…

空间计算时代加速到来,需要的不只是苹果

近年来,科技行业一直在期待“寒武纪”时刻。伴随技术革命的深入推进,所有厂商都预感新的时代即将到来,并期待自己成为那个引爆点,轻轻一触,推开一扇新的未来之门。 今年开年,苹果就为科技圈锚定了一个可能…

Hutool导入导出用法

整理了下Hutool导入导出的简单使用。 导入maven或jar包&#xff08;注意这里导入的poi只是为了优化样式&#xff09; <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --> <dependency><groupId>cn.hutool</groupId><artifactId&g…

2024技术发展洞察与趋势学习总结

2023技术发展洞察 2024技术发展趋势

《Lua程序设计》-- 学习10

环境&#xff08;Environment&#xff09; 具有动态名称的全局变量 全局变量的声明 由于Lua语言将全局变量存放在一个普通的表中&#xff0c;所以可以通过元表来发现访问不存在全局变量的情况。 正如前面所提到的&#xff0c;我们不允许值为nil的全局变量&#xff0c;因为值为…

【Java程序设计】【C00196】基于(JavaWeb+SSM)的旅游管理系统(论文+PPT)

基于&#xff08;JavaWebSSM&#xff09;的旅游管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的旅游平台 本系统分为前台、管理员2个功能模块。 前台&#xff1a;当游客打开系统的网址后&#xff0c;首先看到的…

C# 引用同一个dll不同版本的程序集

因为项目需要所以必须在项目中引用不同版本的同一程序集 我要引用的文件是newtonsoft.json.dll 两个版本为12.0.0.0 和4.0.0.0 1.如果已经先引入了newtonsoft.json 12.0.0.0版本的程序集&#xff0c;如果直接引入另一个版本的程序集的话会提示不成功&#xff0c;所以先将另一个…

分布式ID介绍实现方案总结

分布式 ID 介绍 什么是 ID&#xff1f; 日常开发中&#xff0c;我们需要对系统中的各种数据使用 ID 唯一表示&#xff0c;比如用户 ID 对应且仅对应一个人&#xff0c;商品 ID 对应且仅对应一件商品&#xff0c;订单 ID 对应且仅对应一个订单。 我们现实生活中也有各种 ID&…

BetrFS: A Compleat File System for Commodity SSDs——论文阅读

EuroSys 2022 Paper 分布式元数据论文汇总 问题 在不同的工作负载下&#xff0c;没有单一的Linux文件系统在普通SSD上始终表现良好。我们将一个完备的文件系统定义为在各种微基准测试和应用程序中&#xff0c;没有一个工作负载的性能低于最佳文件系统性能的30%&#xff0c;并…