多线之旅:wait 与 notify

今天小编继续来分享下多线程中的一些内容。

在多线程环境下,由于线程调度的不确定性,所以我们有时候无法很好的去保证其线程的执行顺序。

但是呢,我们又要实现这个顺序执行,所以我们可以使用到这两个方法,wait 和 notify

当然,这两个方法是要在锁内部进行调用的。

那wait 和 notify 方法是什么呢?

wait 


是使当前执行代码的线程进行等待。它还具有另一个带参数的版本:wait(long timeout)

这里的等待,会放进一个等待队列中。

然后,接着会释放当前代码锁的资源

当满足一定的条件过后,它会被唤醒,重新去获取锁。

那这里的条件呢,有这些:

1.其他线程进行notify()

2.当带参数的版本中,时间超出了long timeout,也会被唤醒

3.其他线程中,调用本线程的interrupted方法,导致了wait抛出InterruptedException异常

notify

这个方法是唤醒等待的线程。

这里要值得注意的是

1.notify需要在同步方法或者同步块中使用,因为该方法是去通知可能等待该对象的对象锁的其他线程,并使它们重新获取锁资源。

同步方法:是指synchronized关键字修饰的方法。

同步块:

synchronized(锁){

}

2.如若是多个线程进行等待,那么此时唤醒线程,也是随机的,没有所谓的“先来后到之说”

3.notify方法执行完后,不会立即释放当前锁资源,而是还会等到同步方法,或者同步块执行完。

那来看看这个例子,是如何搭配一起使用的吧

 public static void main(String[] args) throws InterruptedException {Object obj=new Object();Thread t=new Thread(()->{synchronized (obj){System.out.println("notify之前");obj.notify();System.out.println("notify之后");}});System.out.println("wait之前");synchronized(obj){t.start();obj.wait();}System.out.println("wait之后");}

代码结果如下:

wait之前
notify之前
notify之后
wait之后

ok,再次引入一个例子,加深对其的了解吧

比如,我现在要按顺序打印A、B、C

那么我们该如何做呢?

我们可以创建三个线程,两个锁

A线程,打印A,B线程中等待,C等待B线程

打印完A,那就唤醒B线程

打印完B线程,然后去唤醒C线程。

代码如下:

public class Demo21 {public static Object locker=new Object();public static Object locker2=new Object();public static void main(String[] args) throws InterruptedException {Thread A=new Thread(()->{System.out.println("A");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (locker){locker.notify();}});Thread B=new Thread(()->{synchronized (locker){try {locker.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("B");}synchronized (locker2){locker2.notify();}});Thread C=new Thread(()->{synchronized (locker2){try {locker2.wait();} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("C");}});A.start();B.start();C.start();}
}

那么,除了这个notify,还有一个notifyAll

那么这个notifyAll又是什么呢?

notifyAll

notifyAll方法可以一次性唤醒所有的线程等待。

这里值得注意的是,notifyAll多次调用是没有问题,不会出现报错

还有,这个是需要同一把锁,才能全部唤醒

唤醒后,所有线程需要重新获取锁,获取锁的过程是系统决定,依然是具有不确定性。

ok,那么小编就先分享到这里吧。

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

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

相关文章

批量修改mysql字符串字段子字符串

替换子字符串 使用 REPLACE 函数替换字段中的特定子字符串。 示例: 将 table_name 表中 column_name 字段的所有 old_value 替换为 new_value。 UPDATE table_name SET column_name REPLACE(column_name, old_value, new_value) WHERE column_name LIKE %old_val…

达梦:AWR 生成

目录标题 AWR 性能诊断与报告生成1. 检查 AWR 系统状态2. 查看数据库中的所有表空间3. 查看现有的 AWR 快照4. 设置 AWR 快照的时间间隔5. 创建 AWR 快照6. 查看最新的 AWR 快照7. 生成 AWR HTML 报告8. 将 AWR 报告保存到指定文件链接总结 自动工作集负载信息库 AWR 报告解析指…

股票数据接口API实例代码python、JAVA等多种语言演示免费获取实时数据、历史数据、CDMA、KDJ等指标数据配有API说明文档

​ 本文中所有接口均可直接在浏览器打开获取数据,为了便于大家验证有效性,已经做好了超链接,直接点击即可! 沪深两市股票列表 API接口链接(可点击验证):https://api.mairui.club/hslt/list/b…

深入理解DOM:22个核心知识点与代码示例

本文系统介绍DOM相关的22个核心概念,每个知识点均提供代码示例及简要说明,帮助开发者全面掌握DOM操作技巧。 一、DOM基础概念 1. DOM概念 DOM(Document Object Model)是HTML/XML的编程接口,通过JavaScript可动态修改…

【Map vs Set】:Java数据存储的“双子星”对决

个人主页:♡喜欢做梦 欢迎 👍点赞 ➕关注 ❤️收藏 💬评论 目录 🍰一、搜索 🍮1.概念 🍮2.模型 🍰二、Map 🍨1.什么是Map? 🍨2.Map的实例化 &…

【C语言 】C语言 桌游开发数字竞拍(源码)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 【C语言 】C语言 桌游开发数字竞拍(源码…

Reinforcement Learning Heats Up 强化学习持续升温

Reinforcement Learning Heats Up 强化学习持续升温 核心观点:强化学习正成为构建具有高级推理能力大语言模型(LLMs)的重要途径。 最新进展 模型示例:近期出现了如DeepSeek - R1及其变体(DeepSeek - R1 - Zero&#xf…

Whisper+T5-translate实现python实时语音翻译

1.首先下载模型,加载模型 import torch import numpy as np import webrtcvad import pyaudio import queue import threading from datetime import datetime from faster_whisper import WhisperModel from transformers import AutoTokenizer, AutoModelForSeq2…

湖仓分析|浙江霖梓基于 Doris + Paimon 打造实时/离线一体化湖仓架构

导读:浙江霖梓早期使用 CDH 产品套件搭建了大数据系统,面临业务逻辑冗余、查询效率低下等问题,基于 Apache Doris 进行整体架构与表结构的重构,并基于湖仓一体和查询加速展开深度探索与实践,打造了 Doris Paimon 的实…

git bash在github的库中上传或更新本地文件

一、将本地文件上传到 GitHub 仓库 1. 创建 GitHub 仓库 如果你还没有在 GitHub 上创建仓库,首先需要创建一个新的仓库: 登录到 GitHub。点击右上角的 按钮,选择 New repository。给你的仓库起个名字,并选择 Public 或 Privat…

Jmeter压测怎么控制TPS

压测固定TPS的接口 有些任务需要我们控制接口的TPS,例如每秒请求一次。 TPS定时器 然后1个并发持续运行 压测结果 需要注意TPS在1.0/s左右,有时可能是1.2、1.3,定时器会自动调整压力,让TPS保持在1.0左右。

ArcGISPro 新建shp+数据结构

import arcpy# 设置工作空间和 Shapefile 存放路径 shp_path r"C:\path\to\your\folder\PolygonZY.shp" # Shapefile 存放路径 fields [("CHBH", "TEXT", 20),("ZCMC", "TEXT", 100),("ZCLX", "TEXT"…

理解WebGPU 中的 GPUAdapter :连接浏览器与 GPU 的桥梁

在 WebGPU 开发中, GPUAdapter 是一个至关重要的对象,它作为浏览器与 GPU 之间的桥梁,为开发者提供了请求 GPU 设备、查询 GPU 特性以及获取适配器信息的能力。本文将详细介绍 GPUAdapter 的核心属性和方法,并通过实际代码…

信呼OA办公系统sql注入漏洞分析

漏洞描述 信呼OA办公系统uploadAction存在SQL注入漏洞,攻击者可利用该漏洞获取数据库敏感信息。 环境搭建 源码下载地址:https://github.com/rainrocka/xinhu 下载后解压到本地网站根目录下,配置好数据库,然后安装即可 默认密…

vue框架生命周期详细解析

Vue.js 的生命周期钩子函数是理解 Vue 组件行为的关键。每个 Vue 实例在创建、更新和销毁过程中都会经历一系列的生命周期阶段,每个阶段都有对应的钩子函数,开发者可以在这些钩子函数中执行特定的操作。 Vue 生命周期概述 Vue 的生命周期可以分为以下几…

一文深入了解DeepSeek-R1:模型架构

本文深入探讨了 DeepSeek-R1 模型架构。让我们从输入到输出追踪 DeepSeek-R1 模型,以找到架构中的新发展和关键部分。DeepSeek-R1 基于 DeepSeek-V3-Base 模型架构。本文旨在涵盖其设计的所有重要方面。 📝 1. 输入上下文长度 DeepSeek-R1的输入上下文长…

开发基础(8):鸿蒙图表开发

mpchart mpchart是一个包含各种类型图表的图表库,主要用于业务数据汇总,例如销售数据走势图,股价走势图等场景中使用,方便开发者快速实现图表UI,mpchart主要包括线形图、柱状图、饼状图、蜡烛图、气泡图、雷达图、瀑布图等自定义图表库。 柱状图 导入import {BarChart, …

条款03:尽可能使用 const

const 允许我们指定一个语义约束,使某个值应该保持不变 1、const 修饰 变量,指针,函数,函数返回值等,可以使程序减少错误,或者更容易检测错误: 指针常量:int* const p;//指针地址不…

算法兵法全略(译文)

目录 始计篇 谋攻篇 军形篇 兵势篇 虚实篇 军争篇 九变篇 行军篇 地形篇 九地篇 火攻篇 用间篇 始计篇 算法,在当今时代,犹如国家关键的战略武器,也是处理各类事务的核心枢纽。算法的世界神秘且变化万千,不够贤能聪慧…

开关电源实战(一)宽范围DC降压模块MP4560

系列文章目录 文章目录 系列文章目录MP4560MP4560 3.8V 至 55V 的宽输入范围可满足各种降压应用 MOSFET只有250mΩ 输出可调0.8V-52V SW:需要低VF肖特基二极管接地,而且要靠近引脚,高压侧开关的输出。 EN:输入使能,拉低到阈值以下关闭芯片,拉高或浮空启动 COMP:Compens…