乐观锁与悲观锁的使用场景

悲观锁的应用场景
悲观锁的基本思想是假设并发冲突会发生,因此在操作数据时会先锁定数据,直到完成操作并提交事务后才释放锁。这种方式适用于写操作较多、并发冲突可能性较高的场景。

高写入比例的数据库操作:如果系统中有很多写操作,并且这些写操作可能会频繁地相互干扰,那么使用悲观锁可以有效避免数据不一致的问题。
对数据一致性要求高的场景:比如金融交易系统,银行转账,高并发点赞等,需要确保在任何时刻的数据都是一致的,不允许出现脏读、不可重复读等问题。
乐观锁的应用场景
乐观锁则假定并发冲突不会经常发生,因此它不会在开始操作时就锁定资源,而是在提交更新时检查是否有其他事务已经修改了该数据。如果检测到冲突,则拒绝此次操作。乐观锁更适用于读多写少的环境。

读操作远多于写操作的场景:例如在线阅读平台、新闻网站等,这类应用主要以读取信息为主,很少会有数据修改的需求,采用乐观锁可以减少锁带来的性能损耗。
低冲突概率的环境:当系统预期不同事务之间很少会对同一数据进行修改时,使用乐观锁可以获得更好的性能表现。比如库存管理系统中,对于非热销商品的库存调整。
选择哪种锁机制应基于具体的应用场景以及系统对性能和一致性的需求来决定。在实际开发过程中,还需要考虑死锁预防、锁的粒度等因素。

点赞悲观锁实现

以下是基于 Java 和 MyBatis-Plus 实现悲观锁的点赞功能的完整代码示例。

1. 数据库表设计

假设我们有一个 articles 表,包含以下字段:

id: 文章唯一标识。
title: 文章标题。
content: 文章内容。
likes: 点赞数。
sql
深色版本
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
likes INT DEFAULT 0
);

2. 配置 MyBatis-Plus 和数据库连接

2.1 添加依赖
在 pom.xml 文件中添加 MyBatis-Plus 和 MySQL 驱动依赖(与之前一致)。

2.2 配置数据库连接
在 application.yml 中配置数据库连接信息(与之前一致)。

3. 实体类和 Mapper 接口

3.1 创建实体类
java
深色版本

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;@Data
@TableName("articles")
public class Article {@TableIdprivate Long id;private String title;private String content;private Integer likes;
}

3.2 创建 Mapper 接口
java
深色版本

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;@Mapper
public interface ArticleMapper extends BaseMapper<Article> {/*** 悲观锁查询文章*/@Select("SELECT * FROM articles WHERE id = #{id} FOR UPDATE")Article selectForUpdate(Long id);/*** 更新点赞数*/@Update("UPDATE articles SET likes = likes + 1 WHERE id = #{id}")int incrementLikes(Long id);
}

4. 实现点赞功能

4.1 Service 层实现
悲观锁的核心在于使用 FOR UPDATE 锁定数据行,确保在事务提交前其他事务无法修改该行数据。

java
深色版本

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;/*** 使用悲观锁实现点赞*/@Transactional // 开启事务public String likeArticle(Long articleId) {// 使用悲观锁查询文章(锁定该行)Article article = articleMapper.selectForUpdate(articleId);if (article == null) {return "Article not found";}// 更新点赞数int rows = articleMapper.incrementLikes(articleId);if (rows > 0) {return "Like successful, new likes: " + (article.getLikes() + 1);} else {return "Failed to update likes";}}
}

4.2 Controller 层实现
java
深色版本

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/articles")
public class ArticleController {@Autowiredprivate ArticleService articleService;/*** 点赞接口*/@PostMapping("/{id}/like")public String likeArticle(@PathVariable Long id) {return articleService.likeArticle(id);}
}

5. 测试接口

启动 Spring Boot 应用后,可以通过以下方式测试点赞功能:

请求示例
bash
深色版本
POST http://localhost:8080/articles/1/like
响应结果
成功时返回:“Like successful, new likes: X”
如果文章不存在,返回:“Article not found”

6. 核心原理

悲观锁的工作流程:
在查询文章时,使用 FOR UPDATE 锁定目标数据行。
在事务提交之前,其他事务无法对该行数据进行修改。
更新点赞数后提交事务,释放锁。
SQL 示例:
sql
深色版本
– 查询并锁定数据行
SELECT * FROM articles WHERE id = 1 FOR UPDATE;

– 更新点赞数
UPDATE articles SET likes = likes + 1 WHERE id = 1;
适用场景:
适用于写操作较多且并发冲突概率较高的场景。
例如,在高并发环境下对同一篇文章进行频繁点赞时,可以避免数据不一致的问题。

7. 注意事项

性能开销:
悲观锁会锁定数据行,可能导致其他事务阻塞,影响系统性能。
因此,只有在确实需要严格保证数据一致性时才使用悲观锁。
死锁风险:
如果多个事务同时尝试锁定不同的资源,可能会导致死锁。
需要合理设计事务逻辑,尽量减少死锁的可能性。
事务管理:
必须确保在事务中执行锁定和更新操作,否则锁定不起作用。
通过以上代码,我们可以利用悲观锁实现点赞功能,确保在高并发场景下的数据一致性。

点赞乐观锁实现

以下是使用 Java 和 MyBatis-Plus 实现乐观锁的代码示例。我们将基于 Spring Boot 和 MyBatis-Plus 框架完成点赞功能。

1. 数据库表设计

假设我们有一个 articles 表,包含以下字段:

id: 文章唯一标识。
title: 文章标题。
content: 文章内容。
likes: 点赞数。
version: 版本号(用于乐观锁)。
sql
深色版本
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
likes INT DEFAULT 0,
version INT DEFAULT 0
);

2. 配置 MyBatis-Plus 和数据库连接

2.1 添加依赖
在 pom.xml 文件中添加 MyBatis-Plus 和 MySQL 驱动依赖:

xml
深色版本



org.springframework.boot
spring-boot-starter-web

<!-- MyBatis-Plus -->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version>
</dependency><!-- MySQL Driver -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope>
</dependency><!-- Lombok (Optional for code simplification) -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>
2.2 配置数据库连接 在 application.yml 中配置数据库连接信息:

yaml
深色版本
spring:
datasource:
url: jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
username: your_username
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
mapper-locations: classpath:/mapper/*.xml
configuration:
map-underscore-to-camel-case: true

3. 实体类和 Mapper 接口

3.1 创建实体类
使用 @Version 注解来标识版本号字段。

java
深色版本

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;@Data
@TableName("articles")
public class Article {@TableIdprivate Long id;private String title;private String content;private Integer likes;@Versionprivate Integer version; // 版本号字段,用于乐观锁
}

3.2 创建 Mapper 接口
继承 MyBatis-Plus 提供的 BaseMapper 接口。

java
深色版本

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface ArticleMapper extends BaseMapper<Article> {
}

4. 配置乐观锁插件

在 Spring Boot 启动类中配置 MyBatis-Plus 的乐观锁插件。

java
深色版本

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}

5. 实现点赞功能

5.1 Service 层实现
编写点赞逻辑,使用乐观锁更新点赞数。

java
深色版本

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class ArticleService {@Autowiredprivate ArticleMapper articleMapper;public String likeArticle(Long articleId) {// 查询文章信息Article article = articleMapper.selectById(articleId);if (article == null) {return "Article not found";}// 更新点赞数和版本号article.setLikes(article.getLikes() + 1);// 使用 MyBatis-Plus 自动处理乐观锁int rows = articleMapper.updateById(article);if (rows > 0) {return "Like successful, new likes: " + article.getLikes();} else {return "Optimistic lock conflict, please try again";}}
}

5.2 Controller 层实现
提供 RESTful API 接口。

java
深色版本

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/articles")
public class ArticleController {@Autowiredprivate ArticleService articleService;@PostMapping("/{id}/like")public String likeArticle(@PathVariable Long id) {return articleService.likeArticle(id);}
}

6. 测试接口

启动 Spring Boot 应用后,可以通过以下方式测试点赞功能:

请求示例
bash
深色版本
POST http://localhost:8080/articles/1/like
响应结果
成功时返回:“Like successful, new likes: X”
如果发生乐观锁冲突,返回:“Optimistic lock conflict, please try again”

7. 核心原理

乐观锁的核心思想:
在更新数据时,MyBatis-Plus 会自动检查 version 字段是否匹配。
如果匹配,则更新数据并递增 version。
如果不匹配,则更新失败,返回受影响行数为 0。
SQL 示例:
sql
深色版本
UPDATE articles
SET likes = likes + 1, version = version + 1
WHERE id = 1 AND version = current_version;
适用场景:
适用于读多写少且冲突概率较低的场景,如点赞、评论、浏览量统计等。
通过以上代码,我们可以轻松实现基于 MyBatis-Plus 的乐观锁功能,确保在高并发场景下的数据一致性。

银行转账悲观锁实现

在银行转账的场景中,悲观锁是一种非常合适的并发控制机制。由于银行转账涉及资金的流动,数据一致性至关重要,因此使用悲观锁可以确保在事务完成之前,相关账户不会被其他事务修改。

以下是基于 Java 和 MyBatis-Plus 实现银行转账功能的完整代码示例,其中使用了悲观锁来保证事务的安全性。

1. 数据库表设计

假设我们有一个 accounts 表,用于存储用户账户信息:

id: 账户唯一标识。
user_name: 用户名。
balance: 账户余额。
sql
深色版本
CREATE TABLE accounts (
id INT PRIMARY KEY AUTO_INCREMENT,
user_name VARCHAR(255) NOT NULL,
balance DECIMAL(10, 2) NOT NULL DEFAULT 0.00
);

2. 配置 MyBatis-Plus 和数据库连接

2.1 添加依赖
在 pom.xml 文件中添加 MyBatis-Plus 和 MySQL 驱动依赖(与之前一致)。

2.2 配置数据库连接
在 application.yml 中配置数据库连接信息:

yaml
深色版本
spring:
datasource:
url: jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
username: your_username
password: your_password
driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
mapper-locations: classpath:/mapper/*.xml
configuration:
map-underscore-to-camel-case: true

3. 实体类和 Mapper 接口

3.1 创建实体类
java
深色版本

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.math.BigDecimal;@Data
@TableName("accounts")
public class Account {@TableIdprivate Long id;private String userName;private BigDecimal balance;
}

3.2 创建 Mapper 接口
java
深色版本

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;@Mapper
public interface AccountMapper extends BaseMapper<Account> {/*** 悲观锁查询账户*/@Select("SELECT * FROM accounts WHERE id = #{id} FOR UPDATE")Account selectForUpdate(Long id);/*** 更新账户余额*/@Update("UPDATE accounts SET balance = balance + #{amount} WHERE id = #{id}")int updateBalance(Long id, BigDecimal amount);
}

4. 实现转账功能

4.1 Service 层实现
悲观锁的核心在于使用 FOR UPDATE 锁定账户行,确保在事务提交前其他事务无法修改账户余额。

java
深色版本

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.math.BigDecimal;@Service
public class AccountService {@Autowiredprivate AccountMapper accountMapper;/*** 使用悲观锁实现转账** @param fromAccountId 转出账户 ID* @param toAccountId   转入账户 ID* @param amount        转账金额*/@Transactional // 开启事务public String transfer(Long fromAccountId, Long toAccountId, BigDecimal amount) {if (amount.compareTo(BigDecimal.ZERO) <= 0) {return "Invalid transfer amount";}// 查询转出账户并加锁Account fromAccount = accountMapper.selectForUpdate(fromAccountId);if (fromAccount == null || fromAccount.getBalance().compareTo(amount) < 0) {return "Insufficient balance or invalid account";}// 查询转入账户并加锁Account toAccount = accountMapper.selectForUpdate(toAccountId);if (toAccount == null) {return "Invalid target account";}// 执行转账操作accountMapper.updateBalance(fromAccountId, amount.negate()); // 减少转出账户余额accountMapper.updateBalance(toAccountId, amount); // 增加转入账户余额return "Transfer successful";}
}

4.2 Controller 层实现
java
深色版本

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.math.BigDecimal;@RestController
@RequestMapping("/accounts")
public class AccountController {@Autowiredprivate AccountService accountService;/*** 转账接口*/@PostMapping("/transfer")public String transfer(@RequestParam Long fromAccountId,@RequestParam Long toAccountId,@RequestParam BigDecimal amount) {return accountService.transfer(fromAccountId, toAccountId, amount);}
}

5. 测试接口

启动 Spring Boot 应用后,可以通过以下方式测试转账功能:

请求示例
bash
深色版本
POST http://localhost:8080/accounts/transfer?fromAccountId=1&toAccountId=2&amount=100.00
响应结果
成功时返回:“Transfer successful”
如果余额不足或账户无效,返回相应的错误信息。

6. 核心原理

悲观锁的工作流程:
在查询账户时,使用 FOR UPDATE 锁定目标账户的数据行。
在事务提交之前,其他事务无法对该账户进行修改。
完成转账操作后提交事务,释放锁。
SQL 示例:
sql
深色版本
– 查询并锁定账户
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;

– 更新账户余额
UPDATE accounts SET balance = balance - 100.00 WHERE id = 1;
UPDATE accounts SET balance = balance + 100.00 WHERE id = 2;
适用场景:
适用于写操作较多且并发冲突概率较高的场景。
例如,在高并发环境下进行银行转账时,可以避免重复扣款或余额不一致的问题。

7. 注意事项

性能开销:
悲观锁会锁定数据行,可能导致其他事务阻塞,影响系统性能。
因此,只有在确实需要严格保证数据一致性时才使用悲观锁。
死锁风险:
如果多个事务同时尝试锁定不同的资源,可能会导致死锁。
需要合理设计事务逻辑,尽量减少死锁的可能性(例如,按照固定的顺序锁定账户)。
事务管理:
必须确保在事务中执行锁定和更新操作,否则锁定不起作用。
通过以上代码,我们可以利用悲观锁实现银行转账功能,确保在高并发场景下的数据一致性。

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

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

相关文章

cpp(c++)win 10编译GDAL、PROJ、SQLite3、curl、libtiff

cpp&#xff08;c&#xff09;编译GDAL、PROJ、SQLite3 Sqlite3libtiffcurlprojGDAL Sqlite3 1、下载 Sqlite3 源码、工具、二进制预编译 exe Sqlite3 官网&#xff1a;https://www.sqlite.org/download.html 下载 sqlite-amalgamation-3430200.zipsqlite-dll-win64-x64-3430…

【愚公系列】《高效使用DeepSeek》062-图书库存管理

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…

链表算法中常用操作和技巧

目 1.常用技巧 1.1.画图 1.2.添加虚拟头节点 1.3.大胆引入中间变量 1.4.快慢双指针 1.4.1判断链表是否有环 1.4.2找链表中环的入口 ​2.常用操作 2.1. 创建一个新节点 2.2.尾插 2.3.头插 1.常用技巧 1.1.画图 画图可以让一些抽象的文字语言更加形象生动 画图&#…

【9】数据结构的串篇章

目录标题 串的定义顺序串的实现初始化赋值打印串求串的长度复制串判断两个串长度是否相等连接两个串比较两个串内容是否相等插入操作删除操作调试与代码合集 串的模式匹配算法朴素的模式匹配算法KMP算法实现模式匹配 串的定义 定义&#xff1a;由0个或多个字符组成的有限序列&…

GMSL Strapping Pins CFG0/CFG1 应用

GMSL device 使用起来还是比较简单 ADI 已经充分考虑了用户的需求&#xff0c;尽可能的降低的芯片的使用和配置复杂度 一对加串器和解串器&#xff0c;只要工作模式匹配得当&#xff0c;Link Locked&#xff0c;便能够正常工作 如果遇到 Link 无法建立&#xff08;Locked&…

`uia.WindowControl` 是什么:获取窗口文字是基于系统的 UI 自动化接口,而非 OCR 方式

uia.WindowControl 是什么:获取窗口文字是基于系统的 UI 自动化接口,而非 OCR 方式 uia.WindowControl 通常是基于 Windows 系统的 UI 自动化框架(如 pywinauto 中的 uia 模块)里用于表示窗口控件的类。在 Windows 操作系统中,每个应用程序的窗口都可以看作是一个控件,ui…

Easysearch VS Opensearch 数据写入与存储性能对比

本文记录 Easysearch 和 Opensearch 数据写入和数据存储方面的性能对比。 准备 压测工具&#xff1a;INFINI Loadgen 对比版本&#xff1a; Easysearch 1.11.1&#xff08;lucene 8.11.4&#xff09;Opensearch 2.19.1&#xff08;lucene 9.12.1&#xff09; 节点 JVM 配置…

力扣题解:142. 环形链表 II

在链表学习中&#xff0c;我们已经了解了单链表和双链表&#xff0c;两者的最后一个结点都会指向NULL&#xff1b;今天我们介绍的循环列表则不同&#xff0c;其末尾结点指向的这是链表中的一个结点。 循环链表是一种特殊类型的链表&#xff0c;其尾节点的指针指向头节点&#…

区间 dp 系列 题解

1.洛谷 P4342 IOI1998 Polygon 我的博客 2.洛谷 P4290 HAOI2008 玩具取名 题意 某人有一套玩具&#xff0c;并想法给玩具命名。首先他选择 W, I, N, G 四个字母中的任意一个字母作为玩具的基本名字。然后他会根据自己的喜好&#xff0c;将名字中任意一个字母用 W, I, N, G …

天基光学图像仿真原理简介

一、原理简介 天基光学图像仿真通过数学模型和算法模拟空间目标在光学系统中的成像过程&#xff0c;核心原理可归纳为以下四部分&#xff1a; 1. 目标与背景建模‌ 目标运动建模‌&#xff1a;利用轨道动力学模型&#xff08;如SGP4&#xff09;解析空间目标轨迹&#xff0c;…

Jetpack Compose 状态保存机制全面解析:让UI状态持久化

在Android开发中&#xff0c;Jetpack Compose 的状态管理是一个核心话题&#xff0c;而状态保存则是确保良好用户体验的关键。本文将深入探讨Compose中各种状态保存技术&#xff0c;帮助你在配置变更和进程重建时保持UI状态。 一、基础保存&#xff1a;rememberSaveable reme…

【Json-Rpc #1】项目背景及环境搭建

&#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人博客&#xff1a;island ⛺️ 欢迎关注&#xff1a;&#x1f44d;点赞 &#x1f442;&#x1f3fd;留言 &#x1f60d;收藏 &#x1f49e; &#x1f49e; &#x1f49e; 生活总是不会一帆风顺&#xff0c;前进…

WPF轮播图动画交互 动画缩放展示图片

WPF轮播图动画交互 动画缩放展示图片 效果如下图&#xff1a; XAML代码&#xff1a; <Window x:Class"Caroursel.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/20…

为什么 npm list -g 没显示 node_modules?✨

揭秘&#xff1a;为什么 npm list -g 没显示 node_modules&#xff1f;&#x1f575;️‍♂️✨ 嗨&#xff0c;各位代码探险家&#xff01;&#x1f44b; 今天我们要破解一个 npm 小谜团&#xff1a;运行 npm list -g --depth0 时&#xff0c;为什么输出的路径里看不到 node_…

都江堰与郑国渠

目录标题 一、历史背景&#xff1a;地缘博弈下的水利突围都江堰&#xff1a;化水患为天府的千年大计郑国渠&#xff1a;间谍引发的战略反转 二、工程智慧&#xff1a;超越时代的科技奇迹都江堰&#xff1a;生态治水的典范郑国渠&#xff1a;泥沙资源化的创举 三、后世影响&…

链路聚合+vrrp

1.链路聚合 作用注意事项将多个物理接口&#xff08;线路&#xff09;逻辑上绑定在一起形成一条逻辑链路&#xff0c;起到叠加带宽的作用1.聚合接口必须转发速率一致。2.聚合设备两端必须一致 配置命令 方法一 [Huawei]interface Eth-Trunk 0----先创建聚合接口&#xff0c;…

【STM32单片机】#7 定时器输入捕获

主要参考学习资料&#xff1a; B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装&#xff1a;STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…

【android bluetooth 框架分析 01】【关键线程 3】【bt_jni_thread 线程介绍】

1. bt_jni_thread 职责介绍 bt_jni_thread 这个线程的作用是专门负责处理蓝牙 JNI 层的消息循环&#xff0c;也可以说是 C 层和 Java 层交互的桥梁线程。 1.1 什么是 JNI 层&#xff1f;为什么需要这个线程&#xff1f; JNI&#xff08;Java Native Interface&#xff09;是 …

基于视觉语言模型的机器人实时探索系统!ClipRover:移动机器人零样本视觉语言探索和目标发现

作者&#xff1a;Yuxuan Zhang 1 ^{1} 1, Adnan Abdullah 2 ^{2} 2, Sanjeev J. Koppal 3 ^{3} 3, and Md Jahidul Islam 4 ^{4} 4单位&#xff1a; 2 , 4 ^{2,4} 2,4佛罗里达大学电气与计算机工程系RoboPI实验室&#xff0c; 1 , 3 ^{1,3} 1,3佛罗里达大学电气与计算机工程系F…

SpringBoot和微服务学习记录Day2

微服务 微服务将单体应用分割成更小的的独立服务&#xff0c;部署在不同的服务器上。服务间的关联通过暴露的api接口来实现 优点&#xff1a;高内聚低耦合&#xff0c;一个模块有问题不影响整个应用&#xff0c;增加可靠性&#xff0c;更新技术方便 缺点&#xff1a;增加运维…