多线程基础之wait和notify

聚类分析(超全超详细版) 聚类分析是一种典型的无监督学习, 用于对未知类别的样本进行划分,将它们按照一定的规则划分成若干个类族,把相似(距高相近)的样本聚在同一个类簇中, 把不相似的样本分为不同类簇,从而揭示样本之间内在的性质以及相互之间的联系规律 聚类算法在银行、零售、保险、医学、军事等诸多领域有着广泛的应用 聚类分析基础 聚类分析的概念 聚类分析是根据在数据中发现的描述对象及其关系的信息,将数据对象分组。目的是... 阅读详情
  • wait( ),notify( ),notifyAll( )都不属于Thread类,而是属于Object类,也就是每个对象都有wait( ),notify( ),notifyAll( ) 的功能,因为每个对象都有锁,锁是每个对象的基础
  • 当需要调用以上的方法的时候,一定要对竞争资源进行加锁,如果不加锁的话,则会报 IllegalMonitorStateException 异常,也就是说需要配合synchronized使用
  • wait( )会释放当前持有的锁,而notify()和notifyAll( )并不会
  • notify( )方法只会通知等待队列中的第一个相关线程(不会通知优先级比较高的线程)
  • notifyAll( )通知所有等待该竞争资源的线程(也不会按照线程的优先级来执行)
  • 假设有三个线程执行了obj.wait( ),那么obj.notifyAll( )则能全部唤醒tread1,thread2,thread3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,tread1,thread2,thread3只有一个有机会获得锁继续执行,例如tread1,其余的需要等待thread1释放obj锁之后才能继续执行。
  • 当调用obj.notify/notifyAll后,调用线程依旧持有obj锁,因此,thread1,thread2,thread3虽被唤醒,但是仍无法获得obj锁。直到调用线程退出synchronized块,释放obj锁后,thread1,thread2,thread3中的一个才有机会获得锁继续执行。

示例一:

public class ListAdd1 {
    private volatile static List list = new ArrayList();    

    public void add(){
        list.add("Fighting!");
    }
    public int size(){
        return list.size();
    }

    public static void main(String[] args) {
        final ListAdd1 list1 = new ListAdd1();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for(int i = 0; i < 10; i++){
                        list1.add();
                        System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                        Thread.sleep(500);
                    }   
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t1");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    if(list1.size() == 5){
                        System.out.println("当前线程收到通知:" + Thread.currentThread().getName() + " list size = 5 线程停止..");
                        throw new RuntimeException();
                    }
                }
            }
        }, "t2");       

        t1.start();
        t2.start();
    }
}
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程收到通知:t2 list size = 5 线程停止..
Exception in thread "t2" java.lang.RuntimeException
    at ListAdd1$2.run(ListAdd1.java:41)
    at java.lang.Thread.run(Thread.java:748)
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..

这个是没有使用wait( )和notify( )实现的效果,缺点就是在线程1还没有达到指定条件时,线程2是一直处于轮询状态的,这样很耗费资源。我们想要实现的效果是线程1先执行,达到指定条件时再唤醒线程2。

示例二:

public class ListAdd2 {
    private volatile static List list = new ArrayList();    

    public void add(){
        list.add("Fighting!");
    }
    public int size(){
        return list.size();
    }

    public static void main(String[] args) {
        final ListAdd2 list2 = new ListAdd2();
        // 作为对象资源分配锁
        final Object lock = new Object();

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (lock) {
                        System.out.println("t1启动..");
                        for(int i = 0; i <10; i++){
                            list2.add();
                            System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                            Thread.sleep(500);
                            if(list2.size() == 5){
                                System.out.println("已经发出通知..");
                                lock.notify();
                            }
                        }                       
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t1");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    System.out.println("t2启动..");

                    try {
                        System.out.println("t2等待..");
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
                    throw new RuntimeException();
                }
            }
        }, "t2");   
        t2.start();
        t1.start();
    }
}
t2启动..
t2等待..
t1启动..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
已经发出通知..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t2收到通知线程停止..
Exception in thread "t2" java.lang.RuntimeException
    at ListAdd1$2.run(ListAdd1.java:66)
    at java.lang.Thread.run(Thread.java:748)

流程:线程2首先启动,然后是线程1启动,线程2获得锁后执行lock.wait(),之后线程1获得锁后执行循环(wait释放锁),当条件满足时,执行lock.notify(),唤醒了线程2,线程1继续执行(notify不释放锁),等到线程1执行完之后,线程2才接着执行。

问题:我们可以看到示例二的效果和示例一不一样,正是因为notify不释放锁,所以不能在唤醒线程2后让其立即执行。为了改进,达到实时通知并执行的效果,我们可以使用java.util.concurrent包下的CountDownLatch。

示例三:

public class ListAdd3 {
    private volatile static List list = new ArrayList();    

    public void add(){
        list.add("Fighting!");
    }
    public int size(){
        return list.size();
    }

    public static void main(String[] args) {
        final ListAdd3 list3 = new ListAdd3();

        final CountDownLatch countDownLatch = new CountDownLatch(1);

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("t1启动..");
                    for(int i = 0; i <10; i++){
                        list2.add();
                        System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
                        Thread.sleep(500);
                        if(list2.size() == 5){
                            System.out.println("已经发出通知..");
                            countDownLatch.countDown();
                        }
                    }                       
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t1");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("t2启动..");

                try {
                    System.out.println("t2等待..");
                    countDownLatch.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
                throw new RuntimeException();
            }
        }, "t2");   
        t2.start();
        t1.start();
    }
}
t2启动..
t2等待..
t1启动..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
已经发出通知..
当前线程:t2收到通知线程停止..
Exception in thread "t2" java.lang.RuntimeException
    at ListAdd3$3.run(ListAdd3.java:66)
    at java.lang.Thread.run(Thread.java:748)
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
当前线程:t1添加了一个元素..
SAP-ABAP:在SAP系统中,COEP表(成本控制对象行项目表)详解 在SAP系统中,COEP表(成本控制对象行项目表)详解 阅读详情

相关推荐

Mplus实战:三变量随机截距交叉滞后模型(RI-CLPM)语法详解与扩展

本文详细解析了Mplus中三变量随机截距交叉滞后模型(RI-CLPM)的构建原理与语法实现。通过将变量分解为稳定的个体间差异与动态的个体内波动,模型能更纯净地揭示多变量间的纵向交互影响。文章以工作压力、睡眠质量与工作满意度为例,提供了完整的语法模板、关键参数设置(如NOCOV命令、残差相关)及结果解读指南,帮助研究者避开常见误区,稳健分析复杂动态关系。

wdx0123456的博客 926

Java_多线程那点事

ConcurrentHashMap 并发度高,整个 ConcurrentHashMap 对应多把锁,只要线程访问的是不同锁,那么不会冲突。**保证可见性:**用volatile修饰的共享变量,能够防止编译器等jit优化发生,让一个线程对共享变量的修改对另一个线程可见。会导致ABA问题(所谓的ABA问题就是A线程修改B中的原本值修改为新值,另一个A线程又将新值修改为原本值,B无法得知这一变化)ThreadLocal可以实现【资源对象】的线程隔离,让每个线程各用各的【资源对象】,避免争用引发的线程安全问题。

Soil77的博客 170

如何使用windows搭建一个公网ftp/sftp服务器

在有公网ip的情况下,使用windows系统搭建一个ftp/sftp服务器会带来很多的方便,可以实现远程移动端的一键式访问,对于文件的备份、多设备的共享都十分的方便。然而网上许多的教程都是基于windows自带的iis搭建一个局域网ftp服务器,然而在搭建好后,我想要通过端口映射的方式实现在外网访问时,却发现连接不上的问题,感觉可能是因为windows家庭版的原因导致的。因此在查阅很多资料之后终于找到了一个公网ftp/sftp服务器的搭建方式,实测可用。这里把流程记录一下,做一个备忘录,也方便大家搭建。

weixin_43354138的博客 1万+

为什么Java的每个对象都有wait()/notify()方法?

为什么80%的码农都做不了架构师?>>> ...

weixin_34203426的博客 534

【AI Agent系列】【阿里AgentScope框架】0. 快速上手:AgentScope框架简介与你的第一个AgentScope程序

这是我们学习的第四款智能体框架了。前面我们学习了 AutoGPT、MetaGPT、LangGraph 等智能体应用开发框架,各有优缺点。今天我们开始学习AgentScope这一款多智能体开发框架。卷起来吧,多看看,多用用,没坏处。

同学小张的博客 5424

让 ME51N 在采购信息记录过期时不要带出上一次采购订单的价格

在采购信息记录(PIR)价格条件无效或过期时,到上一次采购订单价格进行提议;你可以通过关闭,并在把PO price设置为不采纳,再辅以把过期的价格来源直接拦截为错误。若仍需 100% 阻断,可用在保存前清空估价价格作为技术兜底。标准行为与配置证据见文内引用。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 655

Wait/Notify

一、原理 # 是Object的方法,必须成为锁的owner时候才能使用 # 当前线程一直等待 public final void wait() throws InterruptedException # 当前线程只等待一定时间,到时间后就继续执行了 public final native void wait(long timeoutMillis) throws InterruptedException; # 随便唤醒一个线程 public final native void notify() # 唤醒所有

weixin_43374578的博客 516

OpenCV实现物体尺寸的测量

物体尺寸测量的思路是找一个确定尺寸的物体作为参照物,根据已知的计算未知物体尺寸。如下图所示,绿色的板子尺寸为220*300(单位:毫米),通过程序计算白色纸片的长度。

qq_53545309的博客 9157

多线程

线程的基本概念、线程的本状态以及状态之间的关系 新建 (Born) : 新建的线程处于新建状态 就绪 (Ready) : 在创建线程后,它将处于就绪状态,等待 start() 方法被调用 运行 (Running) : 线程在开始执行时进入运行状态 睡眠 (Sleeping) : 线程的执行可通过使用 sleep() 方法来暂时中止。在睡眠后,线程将进入就绪状态 等待

姚明锋的博客 685

Robot Framework 7.0 报告解析

本文深入解析 Robot Framework 7.0 新增的 JSON 报告功能,手把手教你如何从 output.xml 转换为结构清晰的 output.json,并通过 Python 脚本提取关键测试指标。文章附完整示例、命令、解析脚本,支持导出为 CSV 和 Markdown,方便接入可视化看板、群通知和 CI 流程。适用于测试自动化、质量平台建设和回归趋势分析场景。

点点寒彬的博客 264

蓝桥杯第七届省赛试题--“模拟风扇控制系统”

题目要求 功能简述 “模拟风扇控制系统”能够模拟电风扇工作,通过按键控制风扇的转动速度和定时时间,数码管实时显示风扇的工作模式,动态倒计时显示剩余的定时时间,系统主要由数码管显示、单片机最小系统、按键输入和电机控制保护电路组成,系统框图如图 1 所示: 单总线驱动程序、CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生...

qq_43280087的博客 2658

线程(Thread)的三种等待唤醒机制详解

线程的等待唤醒机制是一种经典的“生产者和消费者”模型。目前可以通过三种方式实现各有优缺点,本篇文章通过实例代码演示三种实现方式以及优缺点。

全栈行动派的博客 4335

YOLOv8 智能交通流量监测完整解决方案

YOLOv8智能交通流量监测系统基于先进的目标检测技术,提供实时车辆识别与统计分析功能。该系统通过虚拟检测线实现多方向车流量统计,支持多种车辆类型分类,并具备数据可视化、异常事件预警等核心功能。完整解决方案包含模型训练、实时检测、批量处理、结果分析等模块,并提供Flask API和Docker两种部署方案。系统采用YOLOv8算法实现高效检测,支持GPU加速,可通过量化、剪枝等技术进一步优化性能,为智能交通管理提供可靠的数据支持和技术保障。

u010117029的博客 117

【多线程】wait 和 notify

合理的协调多个线程之间的执行先后顺序.

HuTool的博客 987

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【多线程基础】 wait和notify

​线程等待wait()和通知notify(),主要用于多线程之间的通信协作,而且这两个方法都是属于Object类,说明任何对象都可以调用这两个方法。 当在一个实例对象上调用了wait()方法之后,当前线程就会在这个对象上等待。直到另外的线程调用了该对象的notify()方法,处于等待状态的线程才得以继续进行。 这样,多线程之间就可以用这两个方法进行通信协作了。

书生-w的博客 2万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

多线程之——wait和notify

本文主要介绍了Java多线程中的线程饥饿问题以及wait/notify机制。线程饥饿是由于synchronized默认采用非公平锁,可能导致某些线程长时间无法获取锁。文章详细讲解了wait()、notify()和notifyAll()方法的使用规则:必须搭配synchronized使用,且操作对象必须一致;wait()要在循环中调用以避免虚假唤醒。通过ABC顺序打印的示例,展示了如何利用这些方法实现线程间的协调控制。最后强调了wait()必须在notify()之前调用才有效,否则无法唤醒等待线程。

2301_79204376的博客 1199

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java多线程wait()和notify()方法图解

多线程场景下 wait 和notify 方法详解,注意事项,内部阻塞队列和等待队列的过程,wait和sleep方法的区别

VIBE的博客 4248

多线程——wait和notify

试想一个这样的场景,ABC三人去atm取钱,当A进入atm后,就会锁上门,也就是对门加锁,此时BC想要进入atm就要等待A开门,也就是释放锁。当A出来后,就会和BC一起参与到“门”这个锁的竞争中,但是,在这个竞争中,刚刚释放锁的A是有优势的,也就是大概率A又会重新拿到这个锁。⽅法notify()也要在同步⽅法或同步块中调⽤,该⽅法是⽤来通知那些可能等待该对象的对象锁的其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。如果不传入参数,那么线程就会无限等待下去,直至被唤醒然后解除等待状态。

slank_noob的博客 815

多线程——wait 和 notify

本文介绍Java多线程中的wait()和notify()方法。两者必须配合同一锁对象使用,且wait()要先于notify()调用。文章还对比了wait()与join()、sleep()的区别,提供生活案例和代码案例分析,以及部分源码解读,适合初学者学习。

2301_76937176的博客 1051

多线程篇五——wait和notify

2.使用wait()时没有设置最大等待时间,而sleep()是在知道最大时限的情况下使用(通过异常唤醒,说明程序应该是出现特殊情况了).调用notify()方法后不会立即释放对象锁,要等到执行notify()方法的线程将程序执行完之后【退出同步代码块】才会释放对象锁.notify()要在同步方法或同步块中调用.它会通知可能等待该对象对象锁的其他线程,使得它们重新获取对象锁.1.wait()可通过notify()唤醒,sleep()通过Interrupt()唤醒。wait()方法的大任(唤醒等待的线程).

weixin_72981769的博客 836

【Java多线程】wait方法和notify方法

介绍wait方法和notify方法

chaodddddd的博客 1426

【多线程】线程饿死以及wait和notify

讲解了线程饿死以及wait和notify

fayifenjihuang的博客 612

Java中多线程wait和notify的用法

本篇文章主要介绍wait和notify的使用,大家可能感到疑惑的问题:比如wait和notify为什么需要加锁?wait和sleep的区别等。

qq_63218110的博客 2775

多线程中的 wait 和 notify 方法

首先先讲一个现象:线程饿死.什么是线程饿死?假如线程1 调度到 cpu 获取到锁, 但它发现要执行的逻辑, 前提条件无法满足, 那么它就无法执行, 进而释放锁, 释放之后 它又和其他线程一起参与锁竞争,但是线程1 当前处于 Runnable 状态, 而其他线程处于BLOCKED状态, 其他线程需要先被系统唤醒,所以很大概率, 又是线程1 获取到锁. 那么如此反复, 就形成了线程饿死.为了避免这种情况, 就要使用 wait 和 notify 方法.

2201_75798628的博客 771

Java多线程之wait和notify的使用

在前面我们已经介绍过了join()方法可以用来控制线程的执行顺序了,但是join()却只能让整个线程执行结束再去执行另外的线程。控制线程执行顺序的效果是有限的,因此又有了wait()和notify(),目的其实都是为了控制程序的执行顺序的。本篇博客就主要来介绍wait()和notify()的使用。wait()方法其实主要做三件事:①把当前线程放进等待队列中②释放锁③被其他线程唤醒时,尝试重新获取锁接下来看一段问题代码:System.out.println("wait()之前");

m0_64986499的博客 968

多线程编程中关于wait和notify关键字

多线程编程中wait和notify关键字以及wait与sleep之间的区别

X_HJJ的博客 1121
上一篇: SpringBoot之集成通用Mapper
下一篇: 多线程之Future模式
章 鱼
博客等级 码龄10年 203粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值