JAVA多线程等待唤醒机制

news2024/12/30 2:42:08

在这里插入图片描述

为什么要处理线程间通信:

当我们需要多个线程来共同完成一件任务,并且我们希望他们有规律的执行,那么多线程之间需要一些通信机制,可以协调它们的工作,以此实现多线程共同操作一份数据。

比如:线程A用来生产包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消费,此时B线程必须等到A线程完成后才能执行,那么线程A与线程B之间就需要线程通信,即—— 等待唤醒机制。

这是多个线程间的一种协作机制。谈到线程我们经常想到的是线程间的竞争(race),比如去争夺锁,但这并不是故事的全部,线程间也会有协作机制。

等待唤醒机制(Wait-Notify Mechanism)是一种用于多线程环境中的同步策略,主要用于实现线程间的通信和同步。这种机制允许一个线程(或多个线程)在特定条件未满足时暂停其执行(等待状态),而当条件满足时,另一个线程可以通知处于等待状态的线程恢复执行(唤醒操作)。等待唤醒机制是多线程编程中的一个核心概念,有助于保证线程安全和资源的有效利用。

主要组成部分

等待唤醒机制主要包括以下几个部分:

  • Wait(): 当一个线程调用对象的 wait() 方法时,它会释放当前持有的锁,并进入等待状态,直到其他线程通过 notify()notifyAll() 方法来唤醒它。

  • wait(long timeout)

    这种方法会在指定的时间后自动唤醒线程,即使没有调用 notify() 方法。

  • 唤醒 (Notify): 当条件满足时,线程可以通过调用对象的 notify()notifyAll() 方法来通知一个或所有处于等待状态的线程,使它们可以重新获取锁并继续执行。

区分sleep()和wait()

相同点:一旦执行,都会使得当前线程结束执行状态,进入阻塞状态。

不同点:

① 定义方法所属的类:sleep():Thread中定义。 wait():Object中定义

② 使用范围的不同:sleep()可以在任何需要使用的位置被调用; wait():必须使用在同步代码块或同步方法中

③ 都在同步结构中使用的时候,是否释放同步监视器的操作不同:sleep():不会释放同步监视器 ;wait():会释放同步监视器

④ 结束等待的方式不同:sleep():指定时间一到就结束阻塞。 wait():可以指定时间也可以无限等待直到notify或notifyAll。

1. 使用 wait()notify()

这是最基本的等待唤醒机制,它们定义在 Object 类中,因此任何对象都可以作为锁对象使用。

public synchronized void doSomething() {
    while (!someCondition) {
        try {
            this.wait();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            // 处理中断
        }
    }
    // 执行操作
}

public synchronized void changeCondition() {
    someCondition = true;
    this.notify(); // 唤醒一个等待的线程
}
2. 使用 wait(long timeout)

这种方法会在指定的时间后自动唤醒线程,即使没有调用 notify() 方法。

public synchronized void doSomething() {
    long start = System.currentTimeMillis();
    while (!someCondition) {
        try {
            long timeout = someConditionTimeout - (System.currentTimeMillis() - start);
            if (timeout > 0) {
                this.wait(timeout);
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            // 处理中断
        }
    }
    // 执行操作
}
3. 使用 Condition 接口

Conditionjava.util.concurrent.locks 包中提供的高级同步工具,可以更灵活地控制线程间的同步。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private boolean someCondition = false;

public void doSomething() {
    lock.lock();
    try {
        while (!someCondition) {
            condition.await();
        }
        // 执行操作
    } finally {
        lock.unlock();
    }
}

public void changeCondition() {
    lock.lock();
    try {
        someCondition = true;
        condition.signal(); // 唤醒一个等待的线程
    } finally {
        lock.unlock();
    }
}
4. 使用 LockSupport

LockSupport 类提供了一种不同的线程阻塞和唤醒机制,可以更精细地控制线程。

import java.util.concurrent.locks.LockSupport;

public void doSomething() {
    while (!someCondition) {
        LockSupport.park(this); // 阻塞当前线程
    }
    // 执行操作
}

public void changeCondition() {
    someCondition = true;
    LockSupport.unpark(Thread.currentThread()); // 唤醒线程
}

注意事项

  • 锁的作用域wait()notify() 必须在同步代码块或同步方法中调用。
  • 中断响应:线程在等待时可能会被中断,需要适当地处理 InterruptedException
  • 锁对象一致性wait()notify() 必须由同一个锁对象调用。
  • 避免死锁:确保线程按照一致的顺序获取锁,防止死锁发生。
  • 正确使用 notifyAll():如果使用 notifyAll(),所有等待线程都会有机会获得锁,但不一定所有线程都能继续执行,因为锁只有一把。

使用场景

等待唤醒机制通常用于以下场景:

  • 生产者-消费者模型

    :生产者生产数据,消费者消费数据。消费者在没有数据可用时等待,而生产者在数据准备好时唤醒消费者

  • 同步数据访问:在线程之间共享资源时,确保线程只在适当条件下访问数据。

  • 线程间的条件同步:线程A等待某个条件满足,线程B在满足条件后唤醒线程A。

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

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

相关文章

Java | Leetcode Java题解之第357题统计各位数字都不同的数字个数

题目&#xff1a; 题解&#xff1a; class Solution {public int countNumbersWithUniqueDigits(int n) {if (n 0) {return 1;}if (n 1) {return 10;}int res 10, cur 9;for (int i 0; i < n - 1; i) {cur * 9 - i;res cur;}return res;} }

4-1-5 步进电机原理2(电机专项教程)

4-1-5 步进电机原理2&#xff08;电机专项教程&#xff09; 4-1-5 步进电机原理2永磁式步进电机反应式步进电机混合式步进电机混合式步进电机基本原理 4-1-5 步进电机原理2 新的步进电机分类 永磁式步进电机 目前学习的转子都是永磁铁 反应式步进电机 软磁材料易受到周围磁场…

阿里云魏子珺:阿里云Elasticsearch AI 搜索实践

作者&#xff1a;阿里云魏子珺 【AI搜索 TechDay】是 Elastic 和阿里云联合主办的 AI 技术 Meetup 系列&#xff0c;聚焦企业级 AI 搜索应用和开发者动手实践&#xff0c;旨在帮助开发者在大模型浪潮下升级 AI 搜索&#xff0c;助力业务增长。 阿里云 Elasticsearch 的 AI 搜索…

Nginx笔记(高级)

扩容 通过扩容提升整体吞吐量 单机垂直扩容&#xff1a;硬件资源增加 云服务资源增加 整机&#xff1a;IBM、浪潮、DELL、HP等CPU/主板&#xff1a;更新到主流网卡&#xff1a;10G/40G网卡磁盘&#xff1a;SAS(SCSI) HDD&#xff08;机械&#xff09;、HHD&#xff08;混合&…

OpenCV几何图像变换(5)旋转和缩放计算函数getRotationMatrix2D()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算二维旋转的仿射矩阵。 该函数计算以下矩阵&#xff1a; [ α β ( 1 − α ) ⋅ center.x − β ⋅ center.y − β α β ⋅ center.x ( …

Linux 中断处理与内核线程化——以触摸屏中断为例

文章目录 1 什么是中断&#xff1f;2 传统的中断处理模型3 内核线程与用户进程4 中断线程化的理念5 devm_request_threaded_irq 与 request_irq 的比较6 触摸屏驱动中的中断线程化参考链接封面 本文探讨了 Linux 中断处理的传统模型与中断线程化的理念&#xff0c;以及在触摸屏…

【Python】计算直角三角形的 ∠MBC

有一个直角三角形 ABC&#xff0c;其中角 B 是直角&#xff08;90&#xff09;。点 M 是斜边 AC 的中点。我们需要根据边 AB 和 BC 的长度来计算角 ∠MBC。 在直角三角形中&#xff0c;如果一个角是直角&#xff0c;那么另外两个角的和是90。由于 M 是斜边的中点&#xff0c;根…

turtle画图知识

Turtle库是Python编程语言中的一个库&#xff0c;用于创建各种类型的图形&#xff0c;包括简单圆形、线条、路径和图片。它支持多种图形类型&#xff0c;并且可以绘制出各种复杂的形状。 以下是一些基本的使用方法&#xff1a; 1. 创建一个新的Turtle对象&#xff1a; pytho…

hyperf 协程作用和相关的方法

什么是协程 协程是一种轻量级的线程&#xff0c;由用户代码来调度和管理&#xff0c;而不是由操作系统内核来进行调度&#xff0c;也就是在用户态进行 判断当前是否处于协程环境内 在一些情况下我们希望判断一些当前是否运行于协程环境内&#xff0c; 对于一些兼容协程环境与…

RK3568平台(PWM篇)PWM驱动

一.PWM基础知识 PWM 全称为 Pulse Width Modulation&#xff0c;翻译成中文为脉冲宽度调制&#xff0c;它是一种数字信号控 制模拟电路的技术&#xff0c;可以通过改变高/低电平的占空比来控制平均电压或功率,从而达到对模拟 量的控制目的。 周期(T)&#xff1a;指一个完整的…

Vue条件判断:v-if、v-else、v-else-if、v-show 指令

在程序设计中&#xff0c;条件判断是必不可少的技术。在视图中&#xff0c;经常需要通过条件判断来控制 DOM 的显示状态。Vue.js 提供了相应的指令用于实现条件判断&#xff0c;包括&#xff1a;v-if、v-else、v-else-if、v-show 指令。 1、v-if 指令 v-if 指令可以根据表达式…

机器学习 之 线性回归算法

目录 线性回归&#xff1a;理解与应用 什么是线性回归&#xff1f; 一元线性回归 正态分布的重要性 多元线性回归 实例讲解 数据准备 数据分析 构建模型 训练模型 验证模型 应用模型 代码实现 线性回归&#xff1a;理解与应用 线性回归是一种广泛使用的统计方法&…

企业高性能web服务器,原理及实例

一、Web 服务基础介绍 正常情况下的单次web服务访问流程&#xff1a; 1.1 Web 服务介绍 1993年3月2日&#xff0c;中国科学院高能物理研究所租用AT&T公司的国际卫星信道建立的接入美国SLAC国家实 验室的64K专线正式开通&#xff0c;成为我国连入Internet的第一根专线。 1…

Mycat分片-垂直拆分

目录 场景 配置 测试 全局表配置 续接上篇&#xff1a;MySQ分库分表与MyCat安装配置-CSDN博客 续接下篇&#xff1a;Mycat分片-水平拆分-CSDN博客 场景 在业务系统中, 涉及以下表结构 ,但是由于用户与订单每天都会产生大量的数据, 单台服务器的数据 存储及处理能力是有限…

0x01 GlassFish 任意文件读取漏洞复现

参考文章&#xff1a; 应用服务器glassfish任意文件读取漏洞 - SecPulse.COM | 安全脉搏 fofa 搜索使用该服务器的网站 网络空间测绘&#xff0c;网络空间安全搜索引擎&#xff0c;网络空间搜索引擎&#xff0c;安全态势感知 - FOFA网络空间测绘系统 "glassfish"&…

VUE3-nest前后端部署教程-----4.服务器linux中部署Node.js环境

一.安装分布式版本管理系统Git (Alibaba Cloud Linux 3/2、CentOS 7.x) sudo yum install git -y 二.使用Git将NVM的源码克隆到本地的~/.nvm目录下&#xff0c;并检查最新版本。 git clone https://gitee.com/mirrors/nvm.git ~/.nvm && cd ~/.nvm && gi…

仿Muduo库实现高并发服务器——Server.hpp框架的简单描述

EventLoop模块在本项目中的简单使用&#xff1a; 下面这张图 是channel模块&#xff0c;poller模块&#xff0c;TimerWheel模块&#xff0c;EventLoop模块&#xff0c;LoopThreadPool模块进行组合。便于大家对这个项目的理解&#xff0c;因为代码看起来挺复杂的。 下面这个图&…

2024河南萌新联赛第六场题解

这场的出题组是郑州大学acm实验室&#xff0c;验题组是郑州大学和郑州轻工业大学的志愿者同学们。 官方题解大部分内容是我写的&#xff0c;B题思路部分是对应的出题人自己写的&#xff0c;E题思路以及代码都是对应的出题人写的因为我不会写这个题&#xff0c;题目的题面&…

C++--类和对象(三)

本篇主要是填补前两篇类和对象中的小知识点 第一篇:C--类和对象&#xff08;一&#xff09;-CSDN博客 第二篇:C--类和对象&#xff08;二&#xff09;-CSDN博客 目录 1.初始化列表 2.友元&#xff08;friend&#xff09; 3.内部类 1.初始化列表 在之前实现构造函数的时候&a…

uniapp 总结

uniapp的 发送请求的 responseType是没有 blob这个类型的&#xff0c; responseType: ‘arraybuffer’, uniapp 标准js和浏览器js的区别 downloadFile的原理作用