每日 Java 面试题分享【第 20 天】

欢迎来到每日 Java 面试题分享栏目!
订阅专栏,不错过每一天的练习

今日分享 3 道面试题目!

评论区复述一遍印象更深刻噢~

目录

  • 问题一:什么是 BIO、NIO、AIO?
  • 问题二:什么是 Channel?
  • 问题三:什么是 Selector?

问题一:什么是 BIO、NIO、AIO?


面试官视角拆解:这个问题考察对 Java I/O 模型的体系化理解,以及不同场景下的技术选型能力。回答要体现三个层次:

  1. 基础概念对比(核心特征 + 工作机制)
  2. 底层实现原理(操作系统级支持)
  3. 工程实践考量(适用场景 + 踩坑经验)

一、标准答案模板(逐层递进)

1. BIO(Blocking I/O)同步阻塞模型

原理

  • 1:1 线程模型:每个连接独占线程,accept()read() 等操作阻塞线程直至完成
  • 内核态拷贝:数据从内核缓冲区到用户空间全程阻塞(两次拷贝过程线程无法处理其他请求)
  • Java 实现ServerSocket + Socket 组合,典型代码如下:
// 服务端代码示例
ServerSocket server = new ServerSocket(8080);
while(true) {Socket client = server.accept(); // 阻塞点new Thread(() -> {InputStream in = client.getInputStream();byte[] buffer = new byte[1024];in.read(buffer); // 阻塞点// 处理业务逻辑}).start();
}

痛点

  • 线程数随连接数线性增长(C10K 问题)
  • 线程上下文切换开销大
  • 长连接场景资源利用率低

2. NIO(Non-blocking I/O)同步非阻塞模型

原理

  • IO 多路复用:通过 Selector 轮询注册的 Channel,单线程管理多个连接
  • 零拷贝技术:通过 DirectByteBuffer 减少内核/用户空间拷贝(配合 FileChannel.transferTo)
  • Java 核心类
    • Selector:基于 epoll(Linux)或 kqueue(BSD)实现的事件通知机制
    • Channel:双向通信通道(ServerSocketChannel/SocketChannel)
    • Buffer:数据读写缓冲区
// NIO服务端核心代码结构
Selector selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(8080));
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);while(true) {selector.select(); // 阻塞直到有就绪事件Set<SelectionKey> keys = selector.selectedKeys();Iterator<SelectionKey> iter = keys.iterator();while(iter.hasNext()) {SelectionKey key = iter.next();if(key.isAcceptable()) {// 处理新连接SocketChannel sc = ssc.accept();sc.configureBlocking(false);sc.register(selector, SelectionKey.OP_READ);} else if(key.isReadable()) {// 处理读事件SocketChannel sc = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);sc.read(buffer);// 处理业务逻辑}iter.remove();}
}

优势

  • 单线程处理数千连接(Netty 等框架的底层基础)
  • 更精细的流量控制(通过 Buffer 机制)

挑战

  • 编程复杂度高(需要处理半包、粘包问题)
  • 空轮询 BUG(早期 Linux 内核 epoll 实现问题)

3. AIO(Asynchronous I/O)异步非阻塞模型

原理

  • Proactor 模式:由 OS 内核完成 IO 操作后主动回调通知应用
  • 完全异步read() 操作发起后立即返回,数据就绪后通过回调处理
  • Java 实现AsynchronousServerSocketChannel + CompletionHandler
// AIO服务端示例
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8080));server.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {@Overridepublic void completed(AsynchronousSocketChannel client, Void attachment) {server.accept(null, this); // 继续接收新连接ByteBuffer buffer = ByteBuffer.allocate(1024);client.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer buf) {// 处理读完成事件buf.flip();// 业务处理client.write(buf);}@Overridepublic void failed(Throwable exc, ByteBuffer buf) {exc.printStackTrace();}});}@Overridepublic void failed(Throwable exc, Void attachment) {exc.printStackTrace();}
});

适用场景

  • 长连接、大文件传输等 IO 密集型操作
  • 需要极高吞吐量的金融交易系统

局限性

  • Linux 平台实现不完善(底层仍用 epoll 模拟)
  • 调试复杂度高(回调地狱问题)

二、对比总结(表格形式更易记忆)

维度BIONIOAIO
阻塞类型同步阻塞同步非阻塞异步非阻塞
线程模型1:1(连接: 线程)M:N(多路复用)M:1(回调驱动)
吞吐量极高
编程复杂度高(需处理事件驱动)中(回调链管理)
适用场景低并发短连接高并发长连接超大文件传输
操作系统支持所有平台依赖 epoll/kqueueWindows IOCP 最佳

三、项目实战包装技巧(以电商系统为例)

场景描述

在跨境电商的订单履约系统中,初期使用 BIO 处理物流状态推送,大促期间出现线程数暴涨导致 Full GC 频繁。通过以下步骤改造:

  1. 问题定位:用 Arthas 监控发现 Tomcat 线程池满(大量 Blocked 线程)
  2. 技术选型:改用 Netty(NIO 模型)重构推送服务
  3. 效果验证:单机连接数从 500 提升到 5W+,CPU 利用率下降 40%
  4. 避坑经验:NIO 需要配合心跳机制解决断连检测问题

四、高频追问方向

  1. 为什么 Netty 选择 NIO 而不是 AIO?

    • Linux AIO 成熟度不足,且 NIO 模型通过优化已能达到相近性能
    • Netty 的 Reactor 线程模型足够处理百万并发
  2. select/poll/epoll 的区别?

    • select:线性扫描 fd 集合,O(n) 复杂度,最大 1024 限制
    • poll:链表结构突破数量限制,但依然线性扫描
    • epoll:回调机制 O(1) 复杂度,支持边缘触发 (ET) 模式
  3. 零拷贝如何实现?

    • 堆外内存(DirectBuffer)减少一次拷贝
    • sendfile 系统调用(FileChannel.transferTo)

回答技巧:采用「技术演进叙事」结构:

BIO时代的问题 -> NIO如何解决痛点 -> AIO带来的新可能性 -> 当前工业界最佳实践

既展示技术深度,又体现业务场景结合能力。


问题二:什么是 Channel?


面试官视角拆解:这个问题看似基础,实则考察候选人是否真正理解 NIO 设计哲学。回答要体现三个层次:

  1. 抽象层:Channel 在 NIO 中的角色定位
  2. 实现层:操作系统级 I/O 操作的封装原理
  3. 实践层:不同 Channel 类型的选择与调优技巧

一、标准答案模板(逐层递进)

1. 核心定义(抽象层)

Channel 本质

  • NIO 的传输管道:区别于 BIO 的流式模型,提供双向数据传输能力(可读可写)
  • Buffer 的载体:所有 I/O 操作必须通过 Buffer 交互,实现零拷贝优化基础
  • 事件驱动基础:注册到 Selector 监听 OP_READ/OP_WRITE 等事件

与流的本质区别

// BIO流式操作(单向)
InputStream in = socket.getInputStream(); 
OutputStream out = socket.getOutputStream();// NIO通道操作(双向)
SocketChannel channel = SocketChannel.open();
channel.read(buffer);  // 读模式
buffer.flip();         
channel.write(buffer); // 写模式

2. 主要实现类(实现层)
Channel 类型使用场景关键特性
FileChannel文件读写支持内存映射文件、文件锁
SocketChannelTCP 客户端通信支持非阻塞模式、连接复用
ServerSocketChannelTCP 服务端监听配合 Selector 实现多路复用
DatagramChannelUDP 通信支持组播、数据报边界保持
AsynchronousSocketChannelAIO 通信基于回调机制的异步操作

底层实现机制

  • Linux 系统:通过 fd(文件描述符)关联内核 socket 结构体
  • 零拷贝实现:FileChannel.transferTo() 底层调用 sendfile 系统调用
// 零拷贝示例(文件传输场景)
try (FileChannel src = new FileInputStream("source.txt").getChannel();FileChannel dest = new FileOutputStream("dest.txt").getChannel()) {src.transferTo(0, src.size(), dest); // 避免用户态与内核态数据拷贝
}

3. 工程实践要点(实战层)

场景 1:高并发 IM 系统的心跳检测

  • 问题:长连接保活需要周期性心跳,传统轮询消耗资源
  • Channel 解决方案
// 在SocketChannel上设置空闲检测
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_READ, new AttachData());// 在Selector循环中处理读空闲
Set<SelectionKey> keys = selector.selectedKeys();
for (SelectionKey key : keys) {if (key.isReadable()) {((AttachData)key.attachment()).updateLastActiveTime();} else if ((key.interestOps() & SelectionKey.OP_READ) == 0) {checkIdle(key); // 自定义空闲检测逻辑}
}

场景 2:文件上传服务的性能优化

  • 错误实践:使用 HeapByteBuffer 导致额外拷贝
  • 正确方案
// 使用DirectByteBuffer+FileChannel组合
try (FileChannel channel = FileChannel.open(Paths.get("large.file"), StandardOpenOption.READ)) {ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024); // 1MB直接缓冲区while (channel.read(buffer) != -1) {buffer.flip();// 网络发送或其他处理buffer.clear();}
}

二、高频追问与避坑指南

追问 1:Channel 是线程安全的吗?

  • 标准回答:大多数 Channel 实现非线程安全(如 SocketChannel),多线程操作必须同步。但 FileChannel 的部分方法(如 transferTo)是线程安全的。
  • 源码佐证:查看 SocketChannel 源码可见其内部没有同步控制:
public abstract class SocketChannel extends AbstractSelectableChannelimplements ByteChannel, ScatteringByteChannel, GatheringByteChannel, NetworkChannel {// 所有方法未使用synchronized修饰
}

追问 2:Channel 的 register() 方法执行过程?

  • 底层原理

    1. 将 Channel 关联到 Selector 的内部 fd 集合
    2. 通过 EPollArrayWrapper 修改 epoll 事件监听(Linux 系统)
    3. 返回 SelectionKey 作为事件监听凭证
  • 关键代码路径
    SelectorImpl.register() -> EPollSelectorImpl.doRegister() -> native 方法 epollCtl()


三、项目实战包装示例

背景:某证券交易系统的行情推送服务

  • 初期问题

    • BIO 模型下单机只能支撑 800 并发连接
    • 行情延迟超过 500ms 影响交易决策
  • Channel 化改造

    1. 使用 SocketChannel+Selector 实现 NIO 服务端
    2. 采用 DirectByteBuffer 减少 GC 停顿
    3. 自定义 Protobuf 编解码 Handler 处理行情数据
  • 优化效果

    • 单机连接数提升至 50,000+
    • 99% 的行情推送延迟低于 50ms
    • CPU 利用率从 90% 降至 40%
  • 踩坑记录

    • 未正确调用 buffer.clear() 导致消息重复
    • 未处理 TCP 粘包导致行情解析错误
    • SelectionKey 未及时 cancel() 导致内存泄漏

四、回答结构建议

采用「三段式黄金结构」:
4. 概念定义:一句话说明本质(“Channel 是 NIO 中…”)
5. 技术纵深

  • 核心特性(双向/非阻塞)
  • 与 Selector、Buffer 的协作关系
  • 不同 Channel 类型的适用场景
  1. 实战背书
    • 项目中具体使用场景
    • 性能对比数据
    • 遇到的典型问题及解决方案
[示例话术]  
"在我的上家公司金融风控系统中,我们使用ServerSocketChannel处理银行数据对接。  
通过配置SO_RCVBUF参数优化接收缓冲区大小,配合DirectByteBuffer将文件解析吞吐量提升了3倍。  
但初期因为没有及时关闭未使用的FileChannel,导致出现'too many open files'的系统错误…"  

这种结构既展现理论深度,又体现工程落地能力,完美匹配大厂面试官的考察维度。


问题三:什么是 Selector?


面试官视角拆解:这个问题考察对 NIO 多路复用机制的底层理解,以及高并发场景的工程实践能力。回答需覆盖三个维度:

  1. 核心机制:Selector 在 NIO 中的作用原理
  2. 操作系统映射:不同平台(Linux/Windows)的实现差异
  3. 实战调优:规避空轮询 BUG、处理惊群效应等工程经验

一、标准答案模板(逐层递进)

1. 核心定义与工作原理

Selector 本质

  • I/O 多路复用控制器:单线程管理多个 Channel 的事件监听(OP_ACCEPT/OP_READ/OP_WRITE)
  • 事件驱动基石:通过 select() 轮询已注册 Channel 的就绪状态,避免线程空转
  • 非阻塞关键:与 Channel 的非阻塞模式配合实现高吞吐

工作流程
4. 创建 Selector 并注册 Channel
5. 调用 select() 阻塞等待事件(可设置超时)
6. 遍历 selectedKeys() 处理就绪事件
7. 清理已处理 Key 并重复循环

// 典型代码结构
Selector selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT); // 注册ACCEPT事件while (true) {int readyChannels = selector.select(); // 阻塞直到有事件if (readyChannels == 0) continue;Set<SelectionKey> keys = selector.selectedKeys();Iterator<SelectionKey> iter = keys.iterator();while (iter.hasNext()) {SelectionKey key = iter.next();if (key.isAcceptable()) {handleAccept(key); // 处理新连接} else if (key.isReadable()) {handleRead(key);   // 处理读事件}iter.remove(); // 必须移除已处理Key}
}

2. 操作系统实现差异
平台实现方式特性
Linuxepoll(水平触发)时间复杂度 O(1),支持大量 fd,JDK 1.5+ 默认使用
WindowsIOCP(完成端口)真正的异步 I/O,但 JDK NIO 中仍模拟为 select/poll
macOS/BSDkqueue类似 epoll 的事件通知机制,效率极高

epoll 优势

  • 无需遍历全部 fd,通过回调机制获取就绪事件
  • 使用 mmap 共享内存减少内核 - 用户空间拷贝
  • 支持边缘触发(ET)模式(需手动设置)

3. 工程实践要点

场景 1:规避空轮询 BUG

  • 现象:Linux 内核 epoll 实现缺陷导致 select() 立即返回(100% CPU 占用)
  • 解决方案
    1. 记录 select() 调用次数与时间戳
    2. 当空轮询次数超过阈值时重建 Selector
// Netty的修复方案(NioEventLoop)
long currentTimeNanos = System.nanoTime();
if (currentTimeNanos - time < timeoutMillis) {selectCnt++; // 空轮询计数if (selectCnt > SELECTOR_AUTO_REBUILD_THRESHOLD) {rebuildSelector(); // 重建Selectorselector = this.selector;selectCnt = 0;}
}

场景 2:百万连接优化

  • 参数调优

    // 调整Linux系统参数
    // 最大文件描述符数
    echo "fs.file-max=1000000" >> /etc/sysctl.conf
    // TCP全连接队列大小
    echo "net.core.somaxconn=65535" >> /etc/sysctl.conf
    // TIME_WAIT连接复用
    echo "net.ipv4.tcp_tw_reuse=1" >> /etc/sysctl.conf
    
  • 代码优化

    • 每个 Selector 管理 5-10 万连接(避免单个 Selector 成为瓶颈)
    • 使用主从 Reactor 线程模型(Netty 默认实现)

二、高频追问与避坑指南

追问 1:select() 和 epoll 的区别?

  • 触发方式
    • select/poll:水平触发(LT),只要 fd 就绪就会通知
    • epoll:支持边缘触发(ET),只在状态变化时通知一次
  • 时间复杂度
    • select/poll:O(n) 遍历所有 fd
    • epoll:O(1) 通过回调直接获取就绪 fd

追问 2:Selector 是线程安全的吗?

  • 标准回答:Selector 本身非线程安全,但可通过 wakeup() 方法实现跨线程唤醒

  • 正确用法

    // 线程A调用select()
    selector.select();// 线程B唤醒selector
    selector.wakeup();// 正确同步方式
    synchronized (selector) {selector.selectNow();
    }
    

三、项目实战包装示例

背景:某直播平台的弹幕推送服务

  • 初期痛点

    • 使用 BIO 模型导致推送延迟高达 2 秒
    • 服务器资源消耗过大(单机只能支撑 5000 连接)
  • Selector 化改造

    1. 基于 Selector 实现多路复用推送
    2. 使用内存映射文件处理弹幕持久化
    3. 采用多 Selector 线程组(主从架构)
  • 优化效果

    • 单机连接容量提升至 50 万
    • 平均推送延迟降至 50ms
    • CPU 利用率从 95% 降至 30%
  • 踩坑记录

    • 未及时清理 selectedKeys 导致事件重复处理
    • 未配置 SO_REUSEPORT 导致端口耗尽
    • EpollET 模式未完全读取数据导致消息丢失

四、回答结构建议

采用「问题驱动式」叙事结构:

传统BIO的瓶颈 -> Selector如何解决C10K问题 -> 不同OS的实现差异 -> 实际项目中的效能提升

示例话术
" 在我们自研的物联网网关中,初期使用 BIO 处理设备连接,遇到线程数爆炸的问题。
通过引入 Selector+NIO 模型:
8. 将线程数从 5000+ 降为固定 4 个(主从 Reactor 模式)
9. 使用 Netty 的 EpollEventLoopGroup 利用 Linux epoll 特性
10. 配合 JVM 参数优化(-XX:+UseEpollWait)减少系统调用开销
最终实现单节点百万设备长连接的稳定管理,但期间也遇到 epoll 空轮询导致 CPU 100% 的问题,通过参考 Netty 的 Selector 重建机制彻底解决…"

这种回答既展示技术深度,又体现实际问题解决能力,完美契合大厂面试的考察要点。


总结

今天的 3 道 Java 面试题,您是否掌握了呢?持续关注我们的每日分享,深入学习 Java 面试的各个细节,快速提升技术能力!如果有任何疑问,欢迎在评论区留言,我们会第一时间解答!

明天见!🎉

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

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

相关文章

如何解决云台重力补偿?

如何解决云台重力补偿? 最近在调试步兵云台的时候,由于枪管、图传、摄像头等重力的原因,pitch轴的参数尤其难以调整,又不想抬升和降低使用两套不同的参数,所以使用了重力补偿,效果也是比较理想的,于是整理为一篇文章记录一下 一、问题根源:枪管重力在“搞事情” 想象…

Vue指令v-html

目录 一、Vue中的v-html指令是什么&#xff1f;二、v-html指令与v-text指令的区别&#xff1f; 一、Vue中的v-html指令是什么&#xff1f; v-html指令的作用是&#xff1a;设置元素的innerHTML&#xff0c;内容中有html结构会被解析为标签。 二、v-html指令与v-text指令的区别…

软考高项笔记 信息技术及其发展

信息技术及其发展 ❝ 信息系统项目管理师第二章第一节 1. 网络标准协议的定义 网络协议是为计算机网络中进行数据交换而建立的规则、标准或约定的集合。网络协议由三个要素组成&#xff0c;分别是语义、语法和时序。 语义&#xff1a;解释控制信息每个部分的含义&#xff0c;它…

【C++ STL】vector容器详解:从入门到精通

【C STL】vector容器详解&#xff1a;从入门到精通 摘要&#xff1a;本文深入讲解C STL中vector容器的使用方法&#xff0c;涵盖常用函数、代码示例及注意事项&#xff0c;助你快速掌握动态数组的核心操作&#xff01; 一、vector概述 vector是C标准模板库&#xff08;STL&am…

深入解析 Chrome 浏览器的多进程架构:标签页是进程还是线程?(中英双语)

深入解析 Chrome 浏览器的多进程架构&#xff1a;标签页是进程还是线程&#xff1f; 1. 引言 Google Chrome 作为全球最流行的浏览器之一&#xff0c;以其稳定性、安全性和多任务处理能力而闻名。而其高效的表现&#xff0c;很大程度上归功于其独特的多进程架构&#xff08;M…

模型蒸馏(ChatGPT文档)

文章来源&#xff1a; https://chatgpt.cadn.net.cn/docs/guides_distillation 模型蒸馏 使用蒸馏技术改进较小的模型。 模型蒸馏允许您利用大型模型的输出来微调较小的模型&#xff0c;使其能够在特定任务上实现类似的性能。此过程可以显著降低成本和延迟&#xff0c;因为较小…

树莓派pico入坑笔记,触摸引脚

这里主要是扒一扒官方是如何实现触摸引脚的功能的&#xff0c;rp2040本身是不支持触摸传感的&#xff0c;那么官方是怎么实现的呢&#xff0c;这件事一直困扰着我&#xff0c;在官方给出的使用中&#xff0c;要求外接一颗至少为1M欧姆的电阻下拉&#xff0c;然后就可以使用触摸…

deepseek本地部署+结合思路

deepseek本地部署 配置&#xff1a; 建议配置 运行内存16GB 显卡&#xff1a;4060 操作系统&#xff1a;win11/win10 存储&#xff1a;512GB 一、安装Python 3.11环境&#xff08;参见&#xff09; 超详细的Python安装和环境搭建教程_python安装教程-CSDN博客 二、安装…

加载数据,并切分

# Step 3 . WebBaseLoader 配置为专门从 Lilian Weng 的博客文章中抓取和加载内容。它仅针对网页的相关部分&#xff08;例如帖子内容、标题和标头&#xff09;进行处理。 加载信息 from langchain_community.document_loaders import WebBaseLoader loader WebBaseLoader(w…

AI(计算机视觉)自学路线

本文仅用来记录一下自学路线方便日后复习&#xff0c;如果对你自学有帮助的话也很开心o(*&#xffe3;▽&#xffe3;*)ブ B站吴恩达机器学习->B站小土堆pytorch基础学习->opencv相关知识&#xff08;Halcon或者opencv库&#xff09;->四类神经网络&#xff08;这里跟…

计算机组成原理——存储系统(二)

&#x1f331; "人生最深的裂痕&#xff0c;往往是光照进来的地方。 别怕脚下的荆棘&#xff0c;那是你与平庸划清界限的勋章&#xff1b;别惧眼前的迷雾&#xff0c;星辰永远藏在云层之上。真正的强者不是从未跌倒&#xff0c;而是把每一次踉跄都踏成攀登的阶梯。记住&am…

解锁豆瓣高清海报(二) 使用 OpenCV 拼接和压缩

解锁豆瓣高清海报(二): 使用 OpenCV 拼接和压缩 脚本地址: 项目地址: Gazer PixelWeaver.py pixel_squeezer_cv2.py 前瞻 继上一篇“解锁豆瓣高清海报(一) 深度爬虫与requests进阶之路”成功爬取豆瓣电影海报之后&#xff0c;本文将介绍如何使用 OpenCV 对这些海报进行智…

OSCP - Proving Grounds - Roquefort

主要知识点 githook 注入Linux path覆盖 具体步骤 依旧是nmap扫描开始&#xff0c;3000端口不是很熟悉&#xff0c;先看一下 Nmap scan report for 192.168.54.67 Host is up (0.00083s latency). Not shown: 65530 filtered tcp ports (no-response) PORT STATE SERV…

记忆化搜索和动态规划 --最长回文子串为例

记忆化搜索 记忆化搜索是一种优化递归算法的方法&#xff0c;通过将已经计算过的子问题的结果存储起来&#xff08;通常使用哈希表或数组&#xff09;&#xff0c;避免重复计算相同的子问题。 本质上是通过缓存中间结果来减少计算的重复性。 动态规划 动态规划是通过将问题分…

最新功能发布!AllData数据中台核心菜单汇总

🔥🔥 AllData大数据产品是可定义数据中台,以数据平台为底座,以数据中台为桥梁,以机器学习平台为中层框架,以大模型应用为上游产品,提供全链路数字化解决方案。 ✨奥零数据科技官网:http://www.aolingdata.com ✨AllData开源项目:https://github.com/alldatacenter/…

Windows图形界面(GUI)-QT-C/C++ - QT Stacked Widget

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 一、概述 二、使用场景 1. 多步表单 2. 选项卡界面 3. 状态机界面 三、常见样式 四、属性设置 1. 页面管理 2. 布局管理 3. 信号与槽 五、内容处理 1. 添加页面 2. 移除页面 3.…

TensorFlow 简单的二分类神经网络的训练和应用流程

展示了一个简单的二分类神经网络的训练和应用流程。主要步骤包括&#xff1a; 1. 数据准备与预处理 2. 构建模型 3. 编译模型 4. 训练模型 5. 评估模型 6. 模型应用与部署 加载和应用已训练的模型 1. 数据准备与预处理 在本例中&#xff0c;数据准备是通过两个 Numpy 数…

Compose笔记(三)--DisposableEffect

这一节了解一下DisposableEffect&#xff0c;它是一个可组合函数&#xff0c;主要用于在可组合项进入组合时执行初始化操作&#xff0c;并且在可组合项从组合中移除时执行相应的清理操作。其核心目的是管理与可组合项生命周期相关的资源&#xff0c;避免资源泄漏&#xff0c;比…

【PDF提取局部内容改名】批量获取PDF局部文字内容改名 基于QT和百度云api的完整实现方案

应用场景 1. 档案管理 在企业或机构的档案管理中&#xff0c;常常会有大量的 PDF 格式的文件&#xff0c;如合同、报告、发票等。这些文件的原始文件名可能没有明确的标识&#xff0c;不利于查找和管理。通过批量获取 PDF 局部文字内容并改名&#xff0c;可以根据文件中的关键…

无人机PX4飞控 | PX4源码添加自定义uORB消息并保存到日志

PX4源码添加自定义uORB消息并保存到日志 0 前言 PX4的内部通信机制主要依赖于uORB&#xff08;Micro Object Request Broker&#xff09;&#xff0c;这是一种跨进程的通信机制&#xff0c;一种轻量级的中间件&#xff0c;用于在PX4飞控系统的各个模块之间进行高效的数据交换…