安卓基础组件Looper - 02 native层面的剖析
文章目录
- native使用
- 使用总结
- 创建Looper
- 构造函数创建(不推荐)
- 使用举例
- 源代码
- Looper::prepare
- 获取Looper
- 可忽略
- 初始化Looper
- 主动休眠 `pollAll`
- 主动唤醒 `wake`
- 发送消息 sendMessage
- 轮询消息
native使用
Android Native Looper 机制 - 掘金 (juejin.cn)
/system/core/libutils/include/utils/Looper.h
/system/core/libutils/Looper.cpp
使用总结
总结一下 Native 层 Looper 的使用:
// 初始化Looper对象
sp<Looper> mLooper = Looper::prepare(false /*allowNonCallbacks*/);// 可选:文件描述符
// - 添加要检测的文件描述符,
// 当对应事件发生时,调用回调对象中的回调函数
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
// - 删除要检测的文件描述符
mLooper->removeFd(inputChannel->getFd());// 进入休眠状态, 等待超时或唤醒的回调
mLooper->pollAll(timeoutMillis);// 主动唤醒
mLooper->wake();// 发送消息 mLooper->sendMessage(handler, message);
// 删除消息 mLooper->removeMessages(handler, message);
void IrisService::runInThread(std::function<void()> handler, std::string tag, bool log) {mLooper->sendMessage(new LambdaMessage(handler, tag), Message());void ReportHandler::scheduleStreamingReport() {mHandlerLooper->removeMessages(this, WHAT_TAKE_REPORT);mHandlerLooper->sendMessage(this, Message(WHAT_TAKE_REPORT));
Android Native 层的 Looper 机制,关注的重点是:
- 如何实现休眠与唤醒
- 如何封装通知
创建Looper
构造函数创建(不推荐)
使用举例
可以使用裸指针,但建议仍然保证一个线程只有一个Looper
的要求。
- 看一下 安卓系统服务surfaceflinger中的做法:
这里在进程的开头,在主线程里创造了一个Looper。所以没有其他子线程,满足 一个线程只有一个Looper
// frameworks/native/services/surfaceflinger/tests/vsync/vsync.cpp
int main(int /*argc*/, char** /*argv*/)
{sp<Looper> loop = new Looper(false);loop->addFd(myDisplayEvent.getFd(), 0, ALOOPER_EVENT_INPUT, receiver,&myDisplayEvent);
- 其他看起来无保护的场景
其他一些地方,在构造函数或init过程中,确确实实是new Looper
了。但也不会多于一个,仍然保证了线程(主线程)只有一个Looper。
// frameworks/base/core/jni/android_os_MessageQueue.cpp
NativeMessageQueue::NativeMessageQueue() :mPollEnv(NULL), mPollObj(NULL), mExceptionObj(NULL) {mLooper = Looper::getForThread();if (mLooper == NULL) {mLooper = new Looper(false);Looper::setForThread(mLooper);}
}
为什么没用
Looper::Prepare
Looper::xxThread
可能出于性能的考虑?
sp<::android::Looper> mLooper;
mLooper = new Looper(false);
源代码
构造函数
# /system/core/libutils/include/utils/Looper.h
# /system/core/libutils/Looper.cpp
Looper::Looper(bool allowNonCallbacks): mAllowNonCallbacks(allowNonCallbacks),mSendingMessage(false),mPolling(false),mEpollRebuildRequired(false),mNextRequestSeq(WAKE_EVENT_FD_SEQ + 1),mResponseIndex(0),mNextMessageUptime(LLONG_MAX) {mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));rebuildEpollLocked();
}
Looper::prepare
更推荐的做法:Looper::prepare
- 如果当前线程已经通过初始化过 Looper(使用构造函数且未使用setForThread指定除外),会直接返回对应Looper
- 设置Looper到当前线程,使用
RefBase::sp<Looper>
智能指针管理Looper对象
// 初始化Looper对象
sp<Looper> mLooper = Looper::prepare(false /*allowNonCallbacks*/);
# /system/core/libutils/include/utils/Looper.h
# /system/core/libutils/Looper.cpp
Looper::Looper(bool allowNonCallbacks): mAllowNonCallbacks(allowNonCallbacks),mSendingMessage(false),mPolling(false),mEpollRebuildRequired(false),mNextRequestSeq(WAKE_EVENT_FD_SEQ + 1),mResponseIndex(0),mNextMessageUptime(LLONG_MAX) {mWakeEventFd.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));rebuildEpollLocked();
}
sp<Looper> Looper::prepare(int opts) {bool allowNonCallbacks = opts & PREPARE_ALLOW_NON_CALLBACKS;sp<Looper> looper = Looper::getForThread();if (looper == nullptr) {looper = new Looper(allowNonCallbacks);Looper::setForThread(looper);}return looper;
}
void Looper::setForThread(const sp<Looper>& looper) {
sp<Looper> Looper::getForThread() {int result = pthread_once(& gTLSOnce, initTLSKey);LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed");return (Looper*)pthread_getspecific(gTLSKey);
}
@TOC
获取Looper
获取当前线程已经绑定的Looper。
如果当前线程已经被 Looper::setForThread
方法指定了 Looper / 通过Looper::prepare
初始化了Looper,那么可以通过 Looper::getForThread
方法获取
# /system/core/libutils/include/utils/Looper.h
# /system/core/libutils/Looper.cpp
static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT;
static pthread_key_t gTLSKey = 0;sp<Looper> Looper::getForThread() {int result = pthread_once(& gTLSOnce, initTLSKey);Looper* looper = (Looper*)pthread_getspecific(gTLSKey);return sp<Looper>::fromExisting(looper);
}void Looper::initTLSKey() {int error = pthread_key_create(&gTLSKey, threadDestructor);LOG_ALWAYS_FATAL_IF(error != 0, "Could not allocate TLS key: %s", strerror(error));
}void Looper::setForThread(const sp<Looper>& looper) {sp<Looper> old = getForThread(); // also has side-effect of initializing TLSif (looper != nullptr)looper->incStrong((void*)threadDestructor);pthread_setspecific(gTLSKey, looper.get());if (old != nullptr) {old->decStrong((void*)threadDestructor);}
}
可忽略
初始化Looper
Looper 的初始化,主要完成以下两个工作:
-
构建一个 epoll 池
-
维护epoll池
- 构造一个 eventfd,放到 epoll 池
- 把 mRequests 中保存的 fd 放到 epoll 池
初始化时 mRequests 为空,这步可暂时忽略
(可选)文件描述符管理 fd
looper->addFd
添加需要关注的 fd (可选)
addfd 添加一个额外的 fd (eventfd 以外的)给 epoll 监听,主要完成了三项工作:
- 根据插入的 fd 回调对象等参数构建一个 Request 对象
- 把参数中的 fd 加入到 epoll 池中
- 把新构建的 Request 对象插入到 mRequests 中
// 可选:文件描述符
// - 添加要检测的文件描述符,
// 当对应事件发生时,调用回调对象中的回调函数
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
// - 删除要检测的文件描述符
mLooper->removeFd(inputChannel->getFd());
主动休眠 pollAll
主动唤醒 wake
looper->pollAll
进入休眠状态等待回调、超时或唤醒
核心功能都聚集于 pollInner 函数中:
-
调用
epoll_wait
进入休眠状态 -
当 IO 事件到来时,被唤醒时
-
读取事件,将发生的事件包装为 Response 对象,并保存到 mResponses 中
-
处理所有的 Response,并回调 addfd 时传入的回调函数
-
处理收到的 message,并调用回调函数
-
// 进入休眠状态, 等待超时或唤醒的回调
mLooper->pollAll(timeoutMillis);// 主动唤醒
mLooper->wake();
发送消息 sendMessage
其他线程是可以通过 Looper::sendMessage
给 Looper 所在工作线程发送消息
-
looper 线程从休眠中唤醒,处理收到的 message,调用回调函数
-
主要完成了两项工作:
-
将
message 截止时间 回调对象
包装为 MessageEnvelope 对象,并插入 mMessageEnvelopes。Looper::pollInner
轮询时,就是从中取出Msg对象的。Vector<MessageEnvelope> mMessageEnvelopes; // guarded by mLock
-
调用 wake 函数,给 eventfd 写数据,唤醒 epoll
-
void IrisService::runInSendingThread(std::function<void()> handler, std::string tag) {mSendingLooper->sendMessage(new LambdaMessage(handler, tag), Message());
}
# /system/core/libutils/include/utils/Looper.h
# /system/core/libutils/Looper.cpp
void Looper::sendMessage(const sp<MessageHandler>& handler, const Message& message) {nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);sendMessageAtTime(now, handler, message);
}
void Looper::sendMessageAtTime(nsecs_t uptime, const sp<MessageHandler>& handler,const Message& message) {size_t i = 0;size_t messageCount = mMessageEnvelopes.size();// 在按照时间顺序,寻找队列中要插入的地方while (i < messageCount && uptime >= mMessageEnvelopes.itemAt(i).uptime) {i += 1;}// 封装可执行对象MessageEnvelope messageEnvelope(uptime, handler, message);mMessageEnvelopes.insertAt(messageEnvelope, i, 1);
轮询消息
native层面传入的message其实就是封装后的std::function
——天然的可执行对象。
轮询实际上是自动完成的,会逐个执行这些可执行对象。
# /system/core/libutils/include/utils/Looper.h
# /system/core/libutils/Looper.cpp
Looper::pollAllLooper::pollOnceLooper::pollInner # 阻塞,轮询
int Looper::pollInner(int timeoutMillis) {// ...// Invoke pending message callbacks.mNextMessageUptime = LLONG_MAX;while (mMessageEnvelopes.size() != 0) {nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);if (messageEnvelope.uptime <= now) {// Remove the envelope from the list.// We keep a strong reference to the handler until the call to handleMessage// finishes. Then we drop it so that the handler can be deleted *before*// we reacquire our lock.{ // obtain handlersp<MessageHandler> handler = messageEnvelope.handler;Message message = messageEnvelope.message;mMessageEnvelopes.removeAt(0);mSendingMessage = true;mLock.unlock();handler->handleMessage(message);} // release handlermLock.lock();mSendingMessage = false;result = POLL_CALLBACK;} else {// The last message left at the head of the queue determines the next wakeup time.mNextMessageUptime = messageEnvelope.uptime;break;}}
相关文章:
安卓基础组件Looper - 02 native层面的剖析
文章目录 native使用使用总结创建Looper构造函数创建(不推荐)使用举例源代码 Looper::prepare 获取Looper可忽略初始化Looper主动休眠 pollAll主动唤醒 wake 发送消息 sendMessage轮询消息 native使用 Android Native Looper 机制 - 掘金 (juejin.cn) /system/core/libutils/…...
nodejs关于后端服务开发的探究
前提 在当前的环境中关于web server的主流开发基本上都是java、php之类的,其中java spring系列基本上占了大头,而python之流也在奋起直追,但别忘了nodejs也是可以做这个服务的,只是位置有点尴尬,现在就来探究下nodejs…...
QTday4
1:是进度条通过线程自己动起来 mythread.h #ifndef MYTHREAD_H #define MYTHREAD_H #include <QThread>class mythread : public QThread {Q_OBJECT public:mythread(QObject* parent nullptr); protected:virtual void run() override; private: signals:virtual voi…...
服务器时间同步
方法一 [rootbogon hwh-ansible]# cat time-sync.sh #!/bin/bash # NTP 服务器信息 NTP_SERVER"192.168.42.12" PASSWORD"123456" # 多个 IP 地址 HOSTS("192.168.42.8" "192.168.42.9" "192.168.42.10" "192.168.42…...
蓝桥杯备赛日记【day1】(c++赛道)
一、裁纸刀问题(2022、规律、思维、省赛) 解法思路: 参考题目给出的例子发现。不管要裁剪多少次。最外围的四次是固定的。然后通过观察发现,我们的行的裁剪次数为(m-1) 次,而每行都需要裁剪列数…...
DeepSeek大模型 —— 全维度技术解析
DeepSeek大模型 —— 全维度技术解析 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家!点我试试!! 文章目录 DeepSeek大模型 —— 全维度技术解析一、模型架构全景解析1.1…...
嵌入式开发:傅里叶变换(5):基于STM32,实现CMSIS中的DSP库
目录 步骤 1:准备工作 步骤 2:创建 Keil 项目,并配置工程 步骤 3:在MDK工程上添加 CMSIS-DSP 库 步骤 5:编写代码 步骤 6:配置时钟和优化 步骤 7:调试与验证 步骤 8:优化和调…...
Ubuntu 24.04 配置ODBC连接ORACLE 11G数据库
1. 安装必要工具和驱动 1.1 安装unixODBC和依赖库 # apt update # apt install unixodbc unixodbc-dev libaio1 执行失败,报错 libaio1包找不到,先跳过,安装其他两个。 # apt install unixodbc unixodbc-dev 安装成功 1.2 下载Oracle…...
upload-labs靶场 1-21通关
目录 1.Pass-01 前端绕过 分析 解题 2.Pass-02 服务器端检测--修改IMME 分析 解题 3.Pass-03 黑名单绕过 分析 解题 4.Pass-04 .htaccess绕过 分析 解题 5.Pass-05 . .绕过和.user.ini绕过 分析 解题 6.Pass-06 大小写绕过 分析 解题 7.Pass-07 空格绕过 分…...
Docker新手入门(持续更新中)
一、定义 快速构建、运行、管理应用的工具。 Docker可以帮助我们下载应用镜像,创建并运行镜像的容器,从而快速部署应用。 所谓镜像,就是将应用所需的函数库、依赖、配置等应用一起打包得到的。 所谓容器,为每个镜像的应用进程创建…...
c语言笔记 指针篇(上)
1.指针 在计算的存储器中有很多的存储单元,我们的操作系统把这些存储单元以字节为单位进行编号,也就是每个存储单元(字节),都有编码。这些编码在我们内存中就称为地址。一个字节有八位,位是存储信息的最小单…...
要查看 SQLite 数据库中的所有表,可以通过查询 SQLite 的系统表 sqlite_master
要查看 SQLite 数据库中的所有表,可以查询 SQLite 的系统表 sqlite_master。 每个 SQLite 数据库都包含一个名为 sqlite_master 的系统表。该表定义了数据库的模式,存储了数据库中所有表、索引、视图和触发器等对象的信息。 通过查询 sqlite_master&am…...
C#释放内存空间的方法
目录 前言释放 C# 对象内存的六种方法1、手动释放内存空间2、使用 Using 语句3、使用 垃圾回收器4、GC.Collect() 方法5、GC.WaitForPendingFinalizers() 方法6、WeakReference 类 注意 前言 当不再需要对象时释放内存空间对于防止内存泄漏和提高应用程序性能至关重要。C# 提供…...
mapbox基础,使用点类型geojson加载symbol符号图层,用于标注文字
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️symbol符号图层样式二、🍀使用点类型…...
Java数组详解/从JVM理解数组/数组反转/随机排名/数组在计算机如何存储
本文详细讲解了数组的定义、数组的访问方法、数组的遍历、静态数组和动态数组、以及数组中的自动类型转换、引用类型指向数组的地址、以及从JVM理解数组、空指针异常、数组反转、随机排名的案例。 数组是存放在连续内存空间上的相同类型数据的集合。 数组可以方便的通过下标索…...
网络安全wireshark题目
一、填空题: 网络安全的目标是在计算机网络的信息传输、存储与处理的整个过程中,提高 物理逻辑上 的防护、监控、反应恢复和 对抗 的能力。SSL协议是在网络传输过程中,提供通信双方网络信息 保密性 和 可靠性 。TCP/IP网络安全管理…...
TomcatServlet
https://www.bilibili.com/video/BV1UN411x7xe tomcat tomcat 架构图,与 jre,应用程序之前的关系 安装使用 tomcat 10 开始,api 从 javax.* 转为使用 jakarta.*,需要至少使用 jdk 11 cmd 中默认 gbk 编码,解决控制…...
Seurat - Guided Clustering Tutorial官方文档学习及复现
由于本人没有使用过Seurat4.0,而是直接使用的最新版。所以本文都是基于Seurat5.2.0(截止2025/3/6)来进行撰写。 参考的官方教程来进行学习(上图中的 Guided tutorial-2.700 PBMCs),肯定没有官方文档那么全面…...
Python数据分析面试题及参考答案
目录 处理 DataFrame 中多列缺失值的 5 种方法 批量替换指定列中的异常值为中位数 使用正则表达式清洗电话号码格式 合并两个存在部分重叠列的 DataFrame 将非结构化 JSON 日志转换为结构化表格 处理日期列中的多种非标准格式(如 "2023 年 12 月 / 05 日") 识…...
极狐GitLab 正式发布安全版本17.9.1、17.8.4、17.7.6
本分分享极狐GitLab 补丁版本 17.9.1、17.8.4、17.7.6 的详细内容。这几个版本包含重要的缺陷和安全修复代码,我们强烈建议所有私有化部署用户应该立即升级到上述的某一个版本。对于极狐GitLab SaaS,技术团队已经进行了升级,无需用户采取任何…...
【JavaSE-7】方法的使用
1、方法的概念和使用 1.1、什么是方法 方法(method)是程序中最小的执行单元,类似于 C语言中的函数,方法存在的意义: 是能够模块化的组织代码(当代码规模比较复杂的时候).做到代码被重复使用, 一份代码可以在多个位置…...
阿里推出全新推理模型(因果语言模型),仅1/20参数媲美DeepSeek R1
阿里Qwen 团队正式发布了他们最新的研究成果——QwQ-32B大语言模型!这款模型不仅名字萌萌哒(QwQ),实力更是不容小觑!😎 QwQ-32B 已在 Hugging Face 和 ModelScope 开源,采用了 Apache 2.0 开源协议。大家可通过 Qwen C…...
C语言笔记(通讯录)
目录 1.通讯录的架构 2.通讯录的功能 3.实现静态通讯录的功能步骤 3.1.创建通讯录数组 3.2.显示功能菜单 3.3.初始化通讯录 3.4.添加联系人的信息 3.5.显示联系人的信息 3.6.查找某个人的信息 3.7.删除某一个联系人信息 3.8.修改某一联系人的信息 3.9.按名字对联系…...
【Manus资料合集】激活码内测渠道+《Manus Al:Agent应用的ChatGPT时刻》(附资源)
DeepSeek 之后,又一个AI沸腾,冲击的不仅仅是通用大模型。 ——全球首款通用AI Agent的破圈启示录 2025年3月6日凌晨,全球AI圈被一款名为Manus的产品彻底点燃。由Monica团队(隶属中国夜莺科技)推出的“全球首款通用AI…...
Python 面向对象高级编程-定制类
目录 __str__ __iter__ __getitem__ __getattr__ __call__ 小结 看到类似__slots__这种形如__xxx__的变量或者函数名就要注意,这些在Python中是有特殊用途的。 __slots__我们已经知道怎么用了,__len__()方法我们也知道是为了能让class作用于len()…...
安装remixd,在VScode创建hardhat
在终端,以管理员身份,cmd 需要科学上网 npm install -g remix-project/remixd 在vscode插件中,安装solidity插件,是暗灰色那款 1.将nodeJs的版本升级至18以上 2.在vscode打开一个新的文件,在终端输入 npx hardhat 3.…...
开发环境搭建-02.后端环境搭建-熟悉项目结构
一.后端环境搭建...
Linux(Centos 7.6)命令详解:vi
1.命令作用 vi/vim 是Linux 系统内置不可或缺的文本编辑命令,vim 是vi 的加强版本,兼容vi 的所有指令,不仅能编辑文本,而且还具有shell 程序编辑的功能,可以不同颜色的字体来辨别语法的正确性。 2.命令语法 usage: …...
Ubuntu 20.04下配置VSCode以支持Eigen库开发
这里写目录标题 1. 安装Eigen库2. 配置VSCode的C开发环境3. 配置c_cpp_properties.json4. 编写代码并测试5. 配置tasks.json(可选)6. 运行程序总结 在VSCode中配置Eigen库(用于线性代数、矩阵和向量运算的C库)的步骤如下ÿ…...
正点原子[第三期]Arm(iMX6U)Linux移植学习笔记-2.1 uboot简介
前言: 本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。 引用: …...
Android14 OTA差分包升级报kPayloadTimestampError (51)
由于VF 架构, 所以镜像的打包时间可能存在偏差, 如 boot.img 和 客制化的一些镜像打包 可能会在 vendor 侧进行打包。 而 与system 侧进行merge 时,时间戳比较乱,为了解决这个问题,让时间戳进行统一。 使用adb方式验证…...
PPT 技能:巧用 “节” 功能,让演示文稿更有序
在制作PPT时,你是否遇到过这样的情况:幻灯片越来越多,内容越来越杂,找某一页内容时翻得眼花缭乱?尤其是在处理大型PPT文件时,如果没有合理的结构,编辑和调整都会变得非常麻烦。这时候࿰…...
Mysql创建库、表练习
创建库 #创建 create database gc_novels default charsetutf8mb4;#default charsetutf8mb4 指定编码为utf-8#使用 use gc_novels#查看当前所在位置 select database(); 结果: 创建表 #创建 create table heros(-> id int,-> name varchar(50),-&…...
【原创】Ollama Test API For Linux/MacOS/Unix
安装Json解析工具 Linux/Unix sudo apt-get install jq -yMacOS brew install jq -y设置环境变量 export IP"192.168.250.229" export PORT"8080" export MODEL"deepseek-r1:7b"检查Ollama版本 curl http://"$IP":"$PORT&qu…...
盛铂科技 SLMF315频率综合器200MHz至15GHz 国产频综模块
在当今科技飞速发展的时代,射频技术在众多领域发挥着关键作用,从通信、雷达系统到科研实验,对频率综合器的性能要求日益严苛。以下是关于盛铂科技的 SLMF315 超低相位噪声频率综合器的介绍: SLMF315超低相位噪声0.2至15GHz频率综合…...
AI-前端开发webcrumbs.ai/frontend-ai,Fitten Code提高开发效率
1.webcrumbs.ai/frontend-ai Frontend AI by Webcrumbshttps://app.webcrumbs.ai/frontend-ai 可选择某一模版进行生成对应版本代码,减少开发量。 2.Fitten Code Vue AI 编程助手 Vue AI 编程助手 | 菜鸟教程https://www.runoob.com/vue2/fitten-code-vue2.htm…...
DeepSeek开源Day4:DualPipeEPLB技术详解
2 月 24 日,DeepSeek 启动 “开源周”,第四个开源的代码库为 DualPipe 与 EPLB(一下发布了两个)。DualPipe 与 EPLB 依然使用了大量与 Hopper 架构绑定的技术。 DualPipe 是由 DeepSeek-AI 团队开发的一种双向流水线并行通信算法&…...
代码随想录算法训练营第22天 | 组合 组合总和 电话号码的字母组合
77. 组合 77. 组合 - 力扣(LeetCode) class Solution {List<Integer> path new ArrayList<>();List<List<Integer>> result new ArrayList<>();public void backTracking(int n,int k,int startIndex){if(path.size() …...
Oracle19c进入EM Express(Oracle企业管理器)详细步骤
以下是使用Oracle 19c进入Oracle Enterprise Manager Database Express(EM Express)的详细步骤: ### **步骤 1:确认EM Express配置状态** 1. **登录数据库服务器** 使用Oracle用户或管理员权限账户登录操作系统。 2. **查看EM…...
Oracle 数据库基础入门(六):视图与索引的深入解析
在 Oracle 数据库的知识体系中,视图与索引是提升数据库操作效率和优化数据管理的重要工具。对于 Java 全栈开发者而言,熟练掌握视图与索引的运用,不仅能够增强数据库查询的性能,还能为构建高效稳定的后端应用提供有力支持。接下来…...
机器学习-随机森林解析
目录 一、.随机森林的思想 二、随机森林构建步骤 1.自助采样 2.特征随机选择 3构建决策树 4.集成预测 三. 随机森林的关键优势 **(1) 减少过拟合** **(2) 高效并行化** **(3) 特征重要性评估** **(4) 耐抗噪声** 四. 随机森林的优缺点 优点 缺点 五.…...
Qt添加MySql数据库驱动
文章目录 一. 安装MySql二.编译mysql动态链接库 Qt版本:5.14.2 MySql版本:8.0.41 一. 安装MySql 参考这里进行安装:https://blog.csdn.net/qq_30150579/article/details/146042922 将mysql安装目录里的bin,include和lib拷贝出来…...
MR的环形缓冲区(底层)
MapReduce的大致流程: 1、HDFS读取数据; 2、按照规则进行分片,形成若干个spilt; 3、进行Map 4、打上分区标签(patition) 5、数据入环形缓冲区(KVbuffer) 6、原地排序ÿ…...
RMAN备份bug-审计日志暴涨(select action from gv$session)
问题概述 /oracle 文件系统使用率过大,经过检查是审计日志过大,/oracle 目录 197G 审计日志占用70G,每6个小时产生大量审计日志,日志内容全是select action from gv$session ,猜测可能跟备份有关, $>df -h /oracle…...
30秒从零搭建机器人管理系统(Trae)
1. 安装 [Trae官网】(https://www.trae.com.cn/) 2. 提示词 创建一个BS架构的机器人远程操控系统,具备机器人状态及位置实时更新,可以实现机器人远程遥控,可以对机器人工作日志进行统计分析,以及其它管理系统的常用功能3. 模型…...
OpenFeign 学习笔记
OpenFeign 学习笔记 一、基础入门 1.1 简介 OpenFeign 是基于声明式的 REST 客户端,用于简化服务间远程调用。(编程式 REST 客户端(RestTemplate)) 通过接口注解方式定义 HTTP 请求,自动实现服务调用。 …...
单例模式(线程案例)
单例模式可以分为两种:1.饿汉模式 2.懒汉模式 一.饿汉模式 //饿汉模式👇 class MySingleTon{//因为这是一个静态成员变量,在类加载的时候,就创建了private static MySingleTon mySingleTon new MySingleTon();//创建一个静…...
HttpServletRequest 和 HttpServletResponse 不同JDK版本的引入
java中,可能会用到JWT令牌校验, 这时,大概率会用到 HttpServletRequest,和 HttpServletResponse。 若为 JDK8,SpringBoot 2.7.3 的版本则引入: import javax.servlet.http.HttpServletRequest; import ja…...
数据安全VS创作自由:ChatGPT与国产AI工具隐私管理对比——论文党程序员必看的避坑指南
文章目录 数据安全VS创作自由:ChatGPT与国产AI工具隐私管理对比——论文党程序员必看的避坑指南ChatGPTKimi腾讯元宝DeepSeek 数据安全VS创作自由:ChatGPT与国产AI工具隐私管理对比——论文党程序员必看的避坑指南 产品隐私设置操作路径隐私协议ChatGPT…...
【JavaEE】SpringMVC简单练习
目录 一、计算器1.1 接口定义1.2 前端代码1.3 后端代码1.4 运行结果 二、⽤⼾登录2.1 需求2.2 接口定义2.3 前端页面2.4 后端代码2.5 结果 三、留⾔板3.1 需求:3.2 接口3.3 前端代码3.4 后端代码3.5 运行结果 四、图书管理系统4.1 需求4.2 接口定义4.3 后端代码 一、计算器 1.…...