线程通信---java
线程
我们知道,线程是进程的最小执行单位,一个进程可以拥有多个线程,那么就会引入两个问题:
- 多个线程之间
如何进行通信
- 多个线程对同一个数据进行操作,如何保证程序正确执行,也就是
线程安全
问题
线程的常用调度方法有:
线程通信和线程安全
线程通信和线程安全并不是完全独立的
- 线程通信依赖线程安全:线程通信通常涉及共享变量或资源的状态变化,而这些共享资源必须是线程安全的,否则通信本身可能失败
- 例子:
使用 wait()/notify() 时,必须在 synchronized 块内操作共享对象的监视器。如果没有同步,线程可能在未持有锁的情况下调用 wait(),导致 IllegalMonitorStateException,或者多个线程同时修改状态,破坏通信逻辑。
- 例子:
- 线程安全需要线程通信:在某些场景下,线程安全不仅需要互斥访问,还需要线程间的协作。例如,一个线程等待条件满足后才能安全访问资源
- 例子:
生产者-消费者模型中,消费者线程需要等待生产者生产数据。如果没有通信机制(比如队列为空时直接访问),会导致数据不一致或异常。
- 例子:
- Java 中许多线程通信和线程安全的实现机制是重叠或互补的
1.共享变量(volatile)
- volatile关键字用于修饰变量,当一个线程修改了volatile修饰的变量的值,其他线程能够立即看到最新的值,从而避免了线程之间的数据不一致(
可见性
) 防止指令重排
,volatile 变量的写入不会被重排序到它之前的代码。- 缺点:
volatile并不能解决多线程并发下的复合操作问题
,比如i++这种操作不是原子操作,如果多个线程同时对i进行自增操作,volatile不能保证线程安全。
public class VolatileExample {private volatile boolean running = true;public void start() {new Thread(() -> {while (running) {System.out.println("线程运行中...");}}).start();}public void stop() {running = false; // 修改立即可见}public static void main(String[] args) throws InterruptedException {VolatileExample example = new VolatileExample();example.start();Thread.sleep(1000);example.stop();}
}
2.wait() / notify() / notifyAll()
- wait() 和 notify() 是定义在 java.lang.Object 类中的方法,用于让线程等待和唤醒线程
- 基于对象监视器(monitor),确保在调用这些方法时,线程已经获得了对象的监视器锁,即**
必须在 synchronized 块内使用
**,否则会抛出 IllegalMonitorStateException。 - 缺点:只能唤醒一个(notify())或全部(notifyAll()),不够灵活
- 内置的 synchronized 关键字
不支持中断等待
,线程如果在进入 synchronized 块前等待锁,就算被中断,也不会停止等待。
public class WaitNotifyExample {private static final Object lock = new Object();private static boolean condition = false;public static void main(String[] args) {// 消费者线程Thread consumer = new Thread(() -> {synchronized (lock) {while (!condition) { // 使用 while 循环等待条件满足try {System.out.println("消费者等待数据...");lock.wait(); // 释放锁并等待} catch (InterruptedException e) {Thread.currentThread().interrupt();e.printStackTrace();}}System.out.println("消费者处理数据...");}});// 生产者线程Thread producer = new Thread(() -> {try {Thread.sleep(1000); // 模拟数据准备时间} catch (InterruptedException e) {Thread.currentThread().interrupt();e.printStackTrace();}synchronized (lock) {condition = true; // 改变条件System.out.println("生产者生产了数据,通知消费者...");lock.notify(); // 唤醒等待中的消费者线程}});consumer.start();producer.start();}
}
3.Lock 和 Condition
- ReentrantLock 提供锁机制,Condition 通过 await() 和 signal() 实现等待和唤醒,是 wait()/notify() 的增强替代品。
可中断性
: ReentrantLock 实现了可中断性,这意味着线程在等待锁的过程中,可以被其他线程中断而提前结束等待。在底层,ReentrantLock 使用了与 LockSupport.park() 和 LockSupport.unpark() 相关的机制来实现可中断性。设置超时时间
: ReentrantLock 支持在尝试获取锁时设置超时时间,即等待一定时间后如果还未获得锁,则放弃锁的获取。这是通过内部的 tryAcquireNanos 方法来实现的。公平锁和非公平锁
: 在直接创建 ReentrantLock 对象时,默认情况下是非公平锁。公平锁是按照线程等待的顺序来获取锁,而非公平锁则允许多个线程在同一时刻竞争锁,不考虑它们申请锁的顺序。公平锁可以通过在创建 ReentrantLock 时传入 true 来设置
ReentrantLock fairLock = new ReentrantLock(true);
可重入性
: ReentrantLock 支持可重入性,即同一个线程可以多次获得同一把锁,而不会造成死锁。这是通过内部的 holdCount 计数来实现的。多个条件变量
: ReentrantLock 支持多个条件变量,每个条件变量可以与一个 ReentrantLock 关联。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;public class ProducerConsumerExample {// 定义一个可重入锁private final Lock lock = new ReentrantLock();// 定义两个条件:notFull 用于生产者等待队列有空位,notEmpty 用于消费者等待队列中有数据private final Condition notFull = lock.newCondition();private final Condition notEmpty = lock.newCondition();// 定义一个缓冲区及相关指针和计数器private final int[] buffer = new int[10];private int count = 0; // 当前存储的数据个数private int putPtr = 0; // 生产者写入数据的位置private int takePtr = 0; // 消费者取数据的位置// 生产者方法:向缓冲区添加数据public void put(int data) throws InterruptedException {lock.lock();try {// 如果缓冲区满了,则等待 notFull 条件满足while (count == buffer.length) {notFull.await();}buffer[putPtr] = data;putPtr = (putPtr + 1) % buffer.length;count++;// 添加数据后,通知消费者:缓冲区不为空了notEmpty.signal();} finally {lock.unlock();}}// 消费者方法:从缓冲区取数据public int take() throws InterruptedException {lock.lock();try {// 如果缓冲区为空,则等待 notEmpty 条件满足while (count == 0) {notEmpty.await();}int data = buffer[takePtr];takePtr = (takePtr + 1) % buffer.length;count--;// 取走数据后,通知生产者:缓冲区有空位了notFull.signal();return data;} finally {lock.unlock();}}public static void main(String[] args) {ProducerConsumerExample example = new ProducerConsumerExample();// 启动生产者线程Thread producer = new Thread(() -> {for (int i = 0; i < 20; i++) {try {example.put(i);System.out.println("Produced: " + i);Thread.sleep(100); // 模拟生产耗时} catch (InterruptedException e) {Thread.currentThread().interrupt();}}});// 启动消费者线程Thread consumer = new Thread(() -> {for (int i = 0; i < 20; i++) {try {int data = example.take();System.out.println("Consumed: " + data);Thread.sleep(150); // 模拟消费耗时} catch (InterruptedException e) {Thread.currentThread().interrupt();}}});producer.start();consumer.start();}
}
4.BlockingQueue(阻塞队列)
- 基于队列(如 ArrayBlockingQueue、LinkedBlockingQueue),通过 put() 和 take() 实现阻塞式数据传递。
- 内BlockingQueue的实现都是线程安全的,所有队列的操作或使用内置锁或是其他形式的并发控制来保证原子。
- 缺点:功能单一,仅限数据传递。容量有限可能导致阻塞。
import java.util.concurrent.*;public class BlockingQueueExample {private BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);public void produce() throws InterruptedException {queue.put("数据"); // 放入数据}public void consume() throws InterruptedException {String data = queue.take(); // 取出数据System.out.println("消费: " + data);}public static void main(String[] args) {BlockingQueueExample example = new BlockingQueueExample();new Thread(() -> {try {example.produce();} catch (InterruptedException e) {e.printStackTrace();}}).start();new Thread(() -> {try {example.consume();} catch (InterruptedException e) {e.printStackTrace();}}).start();}
}
5.Thread.interrupt()
- 通过调用线程的 interrupt() 方法
设置中断标志,等线程自行中断
public class InterruptExample {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("运行中...");try {Thread.sleep(1000);} catch (InterruptedException e) {System.out.println("被中断");return;}}});thread.start();Thread.sleep(3000);thread.interrupt(); // 中断线程}
}
6.CountDownLatch / CyclicBarrier / Semaphore
- CountDownLatch:
允许一个或多个线程等待其他一组线程完成操作后再继续执行
。它通过一个计数器来实现,计数器初始化为线程的数量,每个线程完成任务后调用countDown方法将计数器减一,当计数器为零时,等待的线程可以继续执行。常用于多个线程完成各自任务后,再进行汇总或下一步操作的场景。
import java.util.concurrent.CountDownLatch;public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {int threadCount = 3;CountDownLatch latch = new CountDownLatch(threadCount);for (int i = 0; i < threadCount; i++) {new Thread(() -> {try {// 模拟任务执行Thread.sleep((long) (Math.random() * 1000));System.out.println(Thread.currentThread().getName() + " 完成任务");} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {latch.countDown(); // 任务完成,计数器减一}}).start();}latch.await(); // 等待所有子线程完成System.out.println("所有子线程已完成,主线程继续执行");}
}
- CyclicBarrier:
让一组线程互相等待
,直到所有线程都到达某个屏障点后,再一起继续执行。与CountDownLatch不同的是,CyclicBarrier可以重复使用,当所有线程都通过屏障后,计数器会重置,可以再次用于下一轮的等待。适用于多个线程需要协同工作,在某个阶段完成后再一起进入下一个阶段的场景。
import java.util.concurrent.CyclicBarrier;public class CyclicBarrierExample {public static void main(String[] args) {int threadCount = 3;CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {System.out.println("所有任务已到达屏障点,继续执行...");});for (int i = 0; i < threadCount; i++) {new Thread(() -> {try {// 模拟任务执行Thread.sleep((long) (Math.random() * 1000));System.out.println(Thread.currentThread().getName() + " 到达屏障点");barrier.await(); // 等待其他线程到达System.out.println(Thread.currentThread().getName() + " 继续执行");} catch (Exception e) {Thread.currentThread().interrupt();}}).start();}}
}
- Semaphore:
信号量,用于控制同时访问某个资源的线程数量
。它维护了一个许可计数器,线程在访问资源前需要获取许可,如果有可用许可,则获取成功并将许可计数器减一,否则线程需要等待,直到有其他线程释放许可。常用于控制对有限资源的访问,如数据库连接池、线程池中的线程数量等。
import java.util.concurrent.Semaphore;public class SemaphoreExample {public static void main(String[] args) {int threadCount = 5;Semaphore semaphore = new Semaphore(2); // 允许两个线程同时访问for (int i = 0; i < threadCount; i++) {new Thread(() -> {try {semaphore.acquire(); // 获取许可System.out.println(Thread.currentThread().getName() + " 获取许可,开始执行");// 模拟任务执行Thread.sleep((long) (Math.random() * 1000));System.out.println(Thread.currentThread().getName() + " 释放许可");} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {semaphore.release(); // 释放许可}}).start();}}
}
7. Future 和 Callable
通过 Future 获取线程执行结果,结合 Callable 实现异步通信。
import java.util.concurrent.*;public class FutureExample {public static void main(String[] args) throws Exception {ExecutorService executor = Executors.newSingleThreadExecutor();Future<Integer> future = executor.submit(() -> {Thread.sleep(1000);return 42;});System.out.println("结果: " + future.get()); // 阻塞等待executor.shutdown();}
}
相关文章:
线程通信---java
线程 我们知道,线程是进程的最小执行单位,一个进程可以拥有多个线程,那么就会引入两个问题: 多个线程之间如何进行通信多个线程对同一个数据进行操作,如何保证程序正确执行,也就是线程安全问题 线程的常…...
python面试常见题目
1、python 有几种数据类型 数字:整形 (int),浮点型 (float)布尔 ( bool):false true字符串 (string)列表 (list)元组 (tuple)字典 &…...
Python中与字符串操作相关的30个常用函数及其示例
以下是Python中与字符串操作相关的30个常用函数及其示例: 1. str.capitalize() 将字符串的第一个字符大写,其余字符小写。 s "hello world" print(s.capitalize()) # 输出: Hello world2. str.lower() 将字符串中的所有字符转换为小写。…...
2025年渗透测试面试题总结-小某鹏汽车-安全工程师(题目+回答)
网络安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 小鹏汽车-安全工程师 一、XXE漏洞与SSRF漏洞 1. XXE(XML External Entity)漏洞…...
kafka + flink +mysql 案例
假设你有两个Kafka主题:user_activities_topic 和 product_views_topic,并且你希望将user_activities_topic中的数据写入到user_activities表,而将product_views_topic中的数据写入到product_views表。 maven <dependencies><!-- …...
Windows下配置Flutter移动开发环境以及AndroidStudio安装和模拟机配置
截止 2025/3/9 ,版本更新到了 3.29.1 ,但是为了防止出现一些奇怪的bug,我安装的还是老一点的,3.19,其他版本的安装同理。AndroidStudio用的是 2024/3/1 版本。 — 1 环境变量(Windows) PUB_H…...
【工具类】Springboot 项目日志打印项目版本和构建时间
博主介绍:✌全网粉丝22W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
p5.js:模拟 n个彩色小球在一个3D大球体内部弹跳
向 豆包 提问:编写一个 p5.js 脚本,模拟 42 个彩色小球在一个3D大球体内部弹跳。每个小球都应留下一条逐渐消失的轨迹。大球体应缓慢旋转,并显示透明的轮廓线。请确保实现适当的碰撞检测,使小球保持在球体内部。 cd p5-demo copy…...
RISC-V医疗芯片工程师复合型转型的路径与策略
从RISC-V到医疗芯片:工程师复合型转型的路径与策略 一、引言 1.1 研究背景 在科技快速发展的当下,芯片技术已然成为推动各行业进步的核心驱动力之一。其中,RISC-V 架构作为芯片领域的新兴力量,正以其独特的优势迅速崛起,对整个芯片产业的格局产生着深远影响。RISC-V 架…...
HTML 文本格式化
HTML 文本格式化 在构建网页的过程中,文本的格式化是一个至关重要的环节。HTML(HyperText Markup Language)提供了丰富的标签和属性来帮助我们实现各种文本格式化的需求。本文将详细介绍HTML中常见的文本格式化方法,包括字体、颜…...
基于RNN+微信小程序+Flask的古诗词生成应用
项目介绍 平台采用B/S结构,后端采用主流的Flask框架进行开发,古诗词生成采用RNN模型进行生成,客户端基于微信小程序开发。是集成了Web后台开发、微信小程序开发、人工智能(RNN)等多个领域的综合性应用,是课…...
【算法】图论 —— Dijkstra算法 python
引入 求非负权边的单源最短路 时间复杂度 O( m l o g n mlogn mlogn) 模板 https://www.luogu.com.cn/problem/P4779 import heapq as hq def dijkstra(s): # dis表示从s到i的最短路 dis [float(inf)] * (n 1) # vis表示i是否出队列 vis [0] * (n 1) q [] dis[s…...
Java:LocalDatTime(代替Calendar)、ZoneDateTime(时区时间)
文章目录 Local(代替Calendar)方法:获取当前代码 LocalDate(年月日星期)LocalTime(时分秒纳秒)LocalDateTime(最常用:年月日时分秒纳秒)ZoneId 时区表示方法 ZoneDateTime(时区时间)方法世界标准时间&#…...
HOW - React 如何在在浏览器绘制之前同步执行 - useLayoutEffect
目录 useEffect vs useLayoutEffectuseEffectuseLayoutEffect主要区别总结选择建议注意事项 useLayoutEffect 使用示例测量 DOM 元素的尺寸和位置示例:自适应弹出框定位 同步更新样式以避免闪烁示例:根据内容动态调整容器高度 图像或 Canvas 绘制前的准备…...
PyTorch系列教程:编写高效模型训练流程
当使用PyTorch开发机器学习模型时,建立一个有效的训练循环是至关重要的。这个过程包括组织和执行对数据、参数和计算资源的操作序列。让我们深入了解关键组件,并演示如何构建一个精细的训练循环流程,有效地处理数据处理,向前和向后…...
VS2019,VCPKG - 为VS2019添加VCPKG
文章目录 VS2019,VCPKG - 为VS2019添加VCPKG概述笔记前置条件迁出vcpkg到本地验证库安装更新已经安装的库删除指定的包安装VS2019能用的boostvcpkg 2025.02.14 版本可以给VS2019用用VCPKG的好处备注END VS2019,VCPKG - 为VS2019添加VCPKG 概述 开源工程用到了VCPKG管理的包。…...
linux下 jq 截取json文件信息
背景:通过‘登录名‘ 获取该对象的其他个人信息如名字。 环境准备:麒麟操作系统V10 jq安装包 jq安装包获取方式:yum install jq 或 使用附件中的rpm 或 git自行下载 https://github.com/stedolan/jq/releases/download/ 实现过程介绍&am…...
测试大语言模型在嵌入式设备部署的可能性-ollama本地部署测试
前言 当今各种大语言模型百花齐放,为了方便使用者更加自由的使用大模型,将大模型变成如同棒球棍一样每个人都能用,并且顺手方便的工具,本地私有化具有重要意义。 本次测试使用ollama完成模型下载,过程简单快捷。 1、进…...
C语言基础系列【21】memcpy、memset
博主介绍:程序喵大人 35- 资深C/C/Rust/Android/iOS客户端开发10年大厂工作经验嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手《C20高级编程》《C23高级编程》等多本书籍著译者更多原创精品文章,首发gzh,见文末👇…...
云曦春季开学考复现(2025)
Crypto 划水的dp和dq 下载附件后是简单的RSA算法题,之所以说简单是因为给了公钥e 趁热打铁,昨天刚学的RSA,既然有p有q,也有e,而np*q,可以算出欧拉函数值phi(p-1)*(q-1&…...
探秘 Netty 通信中的 SslHandler 类:保障网络通信安全的基石
引言 在当今数字化时代,网络安全是每一个应用程序都必须重视的关键因素。尤其是在数据传输过程中,防止数据被窃取、篡改至关重要。Netty 作为一个高性能的网络编程框架,为开发者提供了强大的功能来构建可靠的网络应用。其中,SslH…...
Llama factory微调后的模型怎么通过ollama发布
接上一篇博客:用Llama Factory单机多卡微调Qwen2.5时报torch.OutOfMemoryError: CUDA out of memory的解决办法_llama-factory cuda out of memory-CSDN博客 把Lora模块和其基模型merge到一起之后,就可以通过ollama之类的框架提供服务了。不过还是有些格式转换的工作要做: …...
ubuntu 20.04下ZEDmini安装使用
提前安装好显卡驱动和cuda,如果没有安装可以参考我的这两篇文章进行安装: ubuntu20.04配置YOLOV5(非虚拟机)_ubuntu20.04安装yolov5-CSDN博客 ubuntu20.04安装显卡驱动及问题总结_乌班图里怎么备份显卡驱动-CSDN博客 还需要提前…...
CmBacktrace的学习跟移植思路
学习移植CmBacktrace需要从理解其核心功能、适用场景及移植步骤入手,结合理论学习和实践操作。以下是具体的学习思路与移植思路: 一、学习思路 理解CmBacktrace的核心功能 CmBacktrace是针对ARM Cortex-M系列MCU的错误追踪库,支持自动诊断Har…...
Android Glide 缓存模块源码深度解析
一、引言 在 Android 开发领域,图片加载是一个极为常见且关键的功能。Glide 作为一款被广泛使用的图片加载库,其缓存模块是提升图片加载效率和性能的核心组件。合理的缓存机制能够显著减少网络请求,降低流量消耗,同时加快图片显示…...
蓝桥杯备赛:炮弹
题目解析 这道题目是一道模拟加调和级数,难的就是调和级数,模拟过程比较简单。 做法 这道题目的难点在于我们在玩这个跳的过程,可能出现来回跳的情况,那么为了解决这种情况,我们采取的方法是设定其的上限步数。那么…...
死锁问题分析工具
使用 gdb 调试 gdb ./your_program (gdb) run (gdb) thread apply all bt还可以分析pthread_mutex内部,查看owen字段分析哪个线程占用的锁,一个可能的 pthread_mutex 内部结构可以大致表示为: typedef struct pthread_mutex_t {int state; …...
装饰器模式--RequestWrapper、请求流request无法被重复读取
目录 前言一、场景二、原因分析三、解决四、更多 前言 曾经遇见这么一段代码,能看出来是把request又重新包装了一下,核心信息都不会改变 后面了解到这叫 装饰器模式(Decorator Pattern) :也称为包装模式(Wrapper Pat…...
MTK Android12 桌面上显示文件管理器图标
文章目录 需求解决 需求 在MTK平台上,Android12的文件管理器图标未显示在桌面,但在设置里面可以看到,文件管理器是安装的。根据客户要求,需要将文件管理器的图标显示在桌面上。解决 路径:packages/apps/DocumentsUI/…...
SpringBoot实现文件上传
1. 配置文件上传限制 application.yml spring:servlet:multipart:max-file-size: 10MBmax-request-size: 10MB2. 创建文件上传控制器 import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import…...
【开源免费】基于SpringBoot+Vue.JS青年公寓服务平台(JAVA毕业设计)
本文项目编号 T 233 ,文末自助获取源码 \color{red}{T233,文末自助获取源码} T233,文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...
django中视图作用和视图功能 以及用法
在 Django REST Framework(DRF)中,视图(View)是处理 HTTP 请求并返回响应的核心组件。DRF 提供了多种视图类,适用于不同的场景和需求。以下是 DRF 中常见的视图类及其作用、使用方法的详细说明: 一、DRF 视图的分类 DRF 的视图可以分为以下几类: 基于函数的视图(Func…...
大语言模型在患者交互任务中的临床使用评估框架
An evaluation framework for clinical use of large language models in patient interaction tasks An evaluation framework for clinical use of large language models in patient interaction tasks | Nature Medicine 2025.1 收到时间:2023 年 8 月 8 日 …...
Python—类class复习
Python——类(class)复习 根据类来创建对象的方法被称为实例化 因此学会使用类(class)来进行编程就是初步进入面向对象编程的大门 1.1 创建和使用类 首先编写一个小狗的简单类Dog,它表示的不是特定的小狗ÿ…...
QT | 信号与槽(超详解)
前言 对qt信号和槽的详细解释 💓 个人主页:普通young man-CSDN博客 ⏩ 文章专栏:C_普通young man的博客-CSDN博客 ⏩ 本人giee: 普通小青年 (pu-tong-young-man) - Gitee.com 若有问题 评论区见📝 🎉欢迎大家点赞&am…...
Codecraft-17 and Codeforces Round 391 E. Bash Plays with Functions 积性函数
题目链接 题目大意 定义函数 f r ( n ) f_r(n) fr(n) : 在 r 0 r0 r0时,为满足 p p p ⋅ \cdot ⋅ q n qn qn , 且 g c d ( p , q ) 1 gcd(p,q)1 gcd(p,q)1 的有序对 ( p , q ) (p,q) (p,q) 个数;在 r r r ≥ \geq ≥ 1 1 1时࿰…...
粉尘环境下的智能生产革命 ——助力矿山行业实现高效自动化作业
在矿山开采领域,运输系统是保障生产连续性的核心环节。然而,粉尘弥漫、环境恶劣、设备分散等问题,长期制约着矿山运输的效率与安全性。传统的集中式控制系统难以适应复杂工况,而远程分布式 IO 模块与 PLC 的深度融合,正…...
更新vscode ,将c++11更新到c++20
要在CentOS系统中安装最新版本的GCC,你可以使用SCL(Software Collections)仓库,它提供了开发工具的最新版本。以下是安装步骤: 1、 添加SCL仓库: 首先,添加CentOS的SCL仓库,该仓库…...
Numpy实训:读取并分析iris数据集中鸢尾花的相关数据
实训中相关数据集,请联系博主邮箱"1438077481qq.com",在邮箱内发送"iris.csv"即可快速获取,无任何套路,秉承开源精神! 1、导入模块 #导入模块 import numpy as np import csv 2、获取数据 iri…...
nats jetstream server code 分析
对象和缩写 jetstream导入两个对象:stream and consumer,在stream 之上构造jetstreamapi。在nats代码中,以下是一些常见的缩写 1.mset is stream 2.jsX is something of jetstream 3.o is consumer 代码分析 对于producer ,发送…...
德鲁伊连接池
德鲁伊连接池(Druid Connection Pool)是一个开源的Java数据库连接池项目,用于提高数据库连接的性能和可靠性。德鲁伊连接池通过复用数据库连接、定时验证连接的可用性、自动回收空闲连接等机制,有效减少了数据库连接的创建和销毁开…...
Python从入门到精通1:FastAPI
引言 在现代 Web 开发中,API 是前后端分离架构的核心。FastAPI 凭借其高性能、简洁的语法和自动文档生成功能,成为 Python 开发者的首选框架。本文将从零开始,详细讲解 FastAPI 的核心概念、安装配置、路由设计、请求处理以及实际应用案例&a…...
C语言经典案例-菜鸟经典案例
1.输入某年某月某日,判断这一天是这一年的第几天? //输入某年某月某日,判断这一天是这一年的第几天? #include <stdio.h>int isLeapYear(int year) {// 闰年的判断规则:能被4整除且(不能被100整除或…...
SpringBoot过滤器(Filter)的使用:Filter接口、FilterRegistrationBean类配置、@WebFilter注释
1、过滤器(Filter)的介绍 Spring Boot 的过滤器用于对数据进行过滤处理。通过 Spring Boot 的过滤器,程序开发人员不仅可以对用户通过 URL 地址发送的请求进行过滤处理(例如:过滤一些错误的请求或者请求中的敏感词等),而且可以对服务器返回的数据进行过滤处理(例如:压…...
采用内存局部性分配有什么好处?
内存分配时的局部性分配(Locality of Allocation)是指将相关的内存对象分配在相邻或相近的内存区域中。这种分配策略在现代计算机系统中具有显著的好处,主要体现在以下几个方面: 1. 提高缓存命中率 现代计算机系统依赖于多级缓存…...
一周热点-OpenAI 推出了 GPT-4.5,这可能是其最后一个非推理模型
在人工智能领域,大型语言模型一直是研究的热点。OpenAI 的 GPT 系列模型在自然语言处理方面取得了显著成就。GPT-4.5 是 OpenAI 在这一领域的又一力作,它在多个方面进行了升级和优化。 1 新模型的出现 GPT-4.5 目前作为研究预览版发布。与 OpenAI 最近的 o1 和 o3 模型不同,…...
分布式ETCD面试题及参考答案
目录 ETCD 适用的六大场景及其实现原理 ETCD 与 Redis 在分布式锁实现上的差异 解释 ETCD 的 Watch 机制及其应用场景 ETCD 如何实现服务发现?与 ZooKeeper 有何不同? ETCD 实现服务发现的方式 与 ZooKeeper 的不同 ETCD 的键值存储模型支持哪些操作? 为什么 ETCD 适…...
MySQL进阶-关联查询优化
采用左外连接 下面开始 EXPLAIN 分析 EXPLAIN SELECT SQL_NO_CACHE * FROM type LEFT JOIN book ON type.card book.card; 结论:type 有All ,代表着全表扫描,效率较差 添加索引优化 ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】࿰…...
ESP32驱动OV3660摄像头实现EdgeImpulse图像识别(摄像头支持红外夜视、边缘AI计算)
目录 1、传感器特性 2、硬件原理图 3、驱动程序 ESP32-S3 AI智能摄像头模块是一款专为智能家居和物联网应用打造的高性能边缘AI开发模组。它集成了摄像头、麦克风、音频功放、环境光传感器和夜视补光灯,无需依赖云端即可实现本地化AI推理。 凭借TensorFlow Lite、YOLO和O…...
SpringSecurity认证授权完整流程
SpringSecurity认证流程:loadUserByUsername()方法内部实现。 实现步骤: 构建一个自定义的service接口,实现SpringSecurity的UserDetailService接口。建一个service实现类,实现此loadUserByUsername方法。…...