网站建设 广州佛山市北区小型网页设计培训

news/2025/9/23 15:46:07/文章来源:
网站建设 广州佛山,市北区小型网页设计培训,河南省工程项目建设审批系统,维港豪宅项目网站建设前言 最近工作比较忙#xff0c;没怎么记录东西了。Android的Handler重要性不必赘述#xff0c;之前也写过几篇关于hanlder的文章了#xff1a; Handler有多深#xff1f;连环二十七问Android多线程#xff1a;深入分析 Handler机制源码#xff08;二#xff09; And…前言 最近工作比较忙没怎么记录东西了。Android的Handler重要性不必赘述之前也写过几篇关于hanlder的文章了 Handler有多深连环二十七问Android多线程深入分析 Handler机制源码二 Android单个进程其实就是个死循环里面接收handler发来的事件处理所谓的事件驱动系统。本篇文章我们将深入 Native 层一起来探究 Looper#loop() 为什么不会卡死主线程背后的原因。 从 Android 2.3 开始Google 把 Handler 的阻塞/唤醒方案从 Object#wait() / notify()改成了用 Linux epoll 来实现。 原因是 Native 层也引入了一套消息管理机制用于提供给 C/C 开发者使用而现有的阻塞/唤醒方案是为 Java 层准备的只支持 Java。 Native 希望能够像 Java 一样main 线程在没有消息时进入阻塞状态有到期消息需要执行时main 线程能及时醒过来处理。怎么办有两种选择 要么继续使用 Object#wait() / notify( )Native 向消息队列添加新消息时通知 Java 层自己需要什么时候被唤醒要么在 Native 层重新实现一套阻塞/唤醒方案弃用 Object#wait() / notify() Java 通过 jni 调用 Native 进入阻塞态 结局我们都知道了Google 选择了后者。 其实如果只是将 Java 层的阻塞/唤醒移植到 Native 层倒也不用祭出 epoll 这个大杀器 Native 调用 pthread_cond_wait 也能达到相同的效果。 选择 epoll 的另一个原因是 Native 层支持监听 自定义 Fd 比如 Input 事件就是通过 epoll 监听 socketfd 来实现将事件转发到 APP 进程的而一旦有监听多个流事件的需求那就只能使用 Linux I/O 多路复用技术。 理解 I/O多路复用之epoll 说了这么多那到底什么是 epoll epoll 全称 eventpoll是 Linux I/O 多路复用的其中一个实现除了 epoll 外还有 select 和 poll 我们这只讨论 epoll。 要理解 epoll  我们首先需要理解什么是 流 在 Linux 中任何可以进行 I/O 操作的对象都可以看做是流一个 文件 socket pipe我们都可以把他们看作流。 接着我们来讨论流的 I/O 操作通过调用 read() 我们可以从流中读出数据通过 write() 我们可以往流 写入数据。 现在假定一个情形我们需要从流中读数据但是流中还没有数据 int socketfd socket(); connect(socketfd,serverAddr); int n send(socketfd,在吗); n recv(socketfd); //等待接受服务器端 发过来的信息 ...//处理服务器返回的数据一个典型的例子为客户端要从 socket 中读数据但是服务器还没有把数据传回来这时候该怎么办 阻塞 线程阻塞到 recv() 方法直到读到数据后再继续向下执行非阻塞 recv() 方法没读到数据立刻返回 -1 用户线程按照固定间隔轮询 recv() 方法直到有数据返回 好现在我们有了阻塞和非阻塞两种解决方案接着我们同时发起100个网络请求看看这两种方案各自会怎么处理 先说阻塞模式在阻塞模式下一个线程一次只能处理一个流的 I/O 事件想要同时处理多个流只能使用 多线程 阻塞 I/O 的方案。但是每个 socket 对应一个线程会造成很大的资源占用尤其是对于长连接来说线程资源一直不会释放如果后面陆续有很多连接的话很快就会把机器的内存跑完。 在非阻塞模式下我们发现 单线程可以同时处理多个流了。只要不停的把所有流从头到尾的访问一遍就可以得知哪些流有数据返回值大于-1但这样的做法效率也不高因为如果所有的流都没有数据那么只会白白浪费 CPU。 发现问题了吗只有阻塞和非阻塞这两种方案时一旦有监听多个流事件的需求用户程序只能选择要么浪费线程资源阻塞型 I/O要么浪费 CPU 资源非阻塞型 I/O没有其他更高效的方案。 并且这个问题在用户程序端是无解的必须让内核创建某种机制把这些流的监听事件接管过去因为任何事件都必须通过内核读取转发内核总是能在第一时间知晓事件发生。 这种能够让用户程序拥有 “同时监听多个流读写事件” 的机制就被称为 I/O 多路复用 然后我们来看 epoll 提供的三个函数 int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);epoll_create() 用于创建一个 epoll 池epoll_ctl() 用来执行 fd 的 “增删改” 操作最后一个参数 event 是告诉内核 需要监听什么事件。还是以网络请求举例 socketfd  监听的就是 可读事件一旦接收到服务器返回的数据监听 socketfd 的对象将会收到 回调通知表示 socket 中有数据可以读了epoll_wait() 是 使用户线程阻塞 的方法它的第二个参数 events 接受的是一个 集合对象如果有多个事件同时发生events 对象可以从内核得到发生的事件的集合 理解 Linux eventfd 理解了 epoll 我们再来看 Linux eventfd eventfd 是专门用来传递事件的 fd 它提供的功能也非常简单累计计数。 int efd eventfd(); write(efd, 1);//写入数字1 write(efd, 2);//再写入数字2 int res read(efd); printf(res);//输出值为 3通过 write() 函数我们可以向 eventfd 中写入一个 int 类型的值并且只要没有发生 读 操作eventfd 中保存的值将会一直累加。 通过 read() 函数可以将 eventfd 保存的值读了出来并且在没有新的值加入之前再次调用 read() 方法会发生阻塞直到有人重新向 eventfd 写入值。 eventfd 实现的是计数的功能只要 eventfd 计数不为 0 那么表示 fd 是可读的。再结合 epoll 的特性我们可以非常轻松的创建出 生产者/消费者模型。 epoll eventfd 作为消费者大部分时候处于阻塞休眠状态而一旦有请求入队eventfd 被写入值消费者就立刻唤醒处理Handler 机制的底层逻辑就是利用 epoll eventfd。 好有了 epoll 、 eventfd 基础接下来我们开始正式进入 Handler 机制的 Native 世界。 进入Native Handler 绝大多数 Android 工程师都或多或少的了解过 Handler 机制所以关于 Handler 的基本使用和实现的原理我们就不过多赘述了直奔主题。 我们来重点关注 MessageQueue 类中的几个 jni 方法nativeInit()、nativePollOnce() 和 nativeWake() 它们分别对应了 Native 消息队列中的 初始化消息队列、 消息的循环与阻塞 以及 消息的分送与唤醒 这三大环节。 /frameworks/base/core/java/android/os/MessageQueue.java class MessageQueue {private native static long nativeInit();private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/private native static void nativeWake(long ptr);}消息队列的初始化 先来看第一步消息队列的初始化流程 Java MessageQueue 构造函数中会调用 nativeInit() 方法同步在 Native 层也会创建一个消息队列 NativeMessageQueue 对象用于保存 Native 开发者发送的消息。 /frameworks/base/core/java/android/os/MessageQueue.java MessageQueue(boolean quitAllowed) {mQuitAllowed quitAllowed;mPtr nativeInit(); }看代码在 NativeMessageQueue 的构造函数中触发创建 Looper 对象Native 层的 /frameworks/base/core/jni/android_os_MessageQueue.cpp class android_os_MessageQueue {void android_os_MessageQueue_nativeInit() {NativeMessageQueue* nativeMessageQueue new NativeMessageQueue();}NativeMessageQueue() {mLooper Looper::getForThread();if (mLooper NULL) {mLooper new Looper(false);Looper::setForThread(mLooper);}} }Native 创建 Looper 对象的处理逻辑和 Java 一样先去 线程局部存储区 获取 Looper 对象如果为空创建一个新的 Looper 对象并保存到 线程局部存储区。 我们继续接着来看 Native Looper 初始化流程 /system/core/libutils/Looper.cpp class looper {Looper::Looper() {int mWakeEventFd eventfd();rebuildEpollLocked();}void rebuildEpollLocked(){int mEpollFd epoll_create();//哎这儿非常重要在 Looper 初始化时创建了 epoll 对象epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeEventFd, eventItem);//把用于唤醒消息队列的eventfd 添加到 epoll 池}}关键的地方来了 Looper 的构造函数首先创建了 eventfd 对象 mWakeEventFd它的作用就是用来监听 MessageQueue 是否有新消息加入这个对象非常重要一定要记住它 随后调用的 rebuildEpollLocked() 方法中又创建了 epoll 对象mEpollFd并将刚刚申请的 mWakeEventFd 注册到 epoll 池 到这一步Handler 机制最依赖的两大核心对象 mEpollFd 和 mWakeEventFd 全部都初始化成功 我们来梳理一下 消息队列的初始化 步骤 Java 层初始化消息队列时同步调用 nativeInit() 方法在 native 层创建了一个 NativeMessageQueue 对象Native 层的消息队列被创建的同时也会创建一个 Native Looper 对象在 Native Looper 构造函数中调用 eventfd() 生成 mWakeEventFd它是后续用于唤醒消息队列的核心最后调用 rebuildEpollLocked() 方法初始化了一个 epoll 实例 mEpollFd 然后将 mWakeEventFd 注册到 epoll 池 至此Native 层的消息队列初始化完成Looper 对象持有 mEpollFd 和 mWakeEventFd 两大金刚。 消息的循环与阻塞 Java 和 Native 的消息队列都创建完以后整个线程就会阻塞到 Looper#loop() 方法中在 Java 层的的调用链大致是这样的 Looper#loop()- MessageQueue#next()- MessageQueue#nativePollOnce() }MessageQueue 最后一步调用的 nativePollOnce() 是一个 jni 方法具体实现在 Native 层。 我们接着往下跟看看 Native 中做了些什么 /frameworks/base/core/jni/android_os_MessageQueue.cpp class android_os_MessageQueue {//jni方法转到 NativeMessageQueue#pollOnce()void android_os_MessageQueue_nativePollOnce(){nativeMessageQueue-pollOnce(env, obj, timeoutMillis);}class NativeMessageQueue : MessageQueue {/转到 Looper#pollOnce() 方法void pollOnce(){mLooper-pollOnce(timeoutMillis);}} }nativePollOnce() 接受到请求后随手转发到 NativeMessageQueue 的 pollOnce() 方法。 而 NativeMessageQueue#pollOnce() 中什么都没做只是又把请求转发给了 Looper#pollOnce()。 看来主要的逻辑都在 Looper 中我们接着往下看 //system/core/libutils/Looper.cpp class looper {int pollOnce(int timeoutMillis){int result 0;for (;;) {if (result ! 0) {return result;}result pollInner(timeoutMillis);//超时}}int pollInner(int timeoutMillis){int eventCount epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);//调用 epoll_wait() 等待事件的产生} }看到了吗线程阻塞和唤醒的执行逻辑都在这 pollOnce() 会不停的轮询 pollInner() 方法检查它的的返回值 result 这里的 result 类型是在 Looper.h 文件中声明的枚举类一共有4种结果 -1 表示在 “超时时间到期” 之前使用 wake() 唤醒了轮询通常是有需要立刻执行的新消息加入了队列-2 表示多个事件同时发生有可能是新消息加入也有可能是监听的 自定义 fd 发生了 I/O 事件-3 表示设定的超时时间到期了-4 表示错误不知道哪里会用到 消息队列中没消息或者 设定的超时时间没到期再或者 自定义 fd 没有事件发生都会导致线程阻塞到 pollInner() 方法调用。 pollInner() 中则是使用了 epoll_wait() 系统调用等待事件的产生。 本小节标题是 消息的循环与阻塞 现在线程已经阻塞到 pollInner() 我们可以来梳理下发生阻塞的前后逻辑 消息队列在初始化成功以后Java 层的 Looper#loop() 会开始无限轮询不停的获取下一条消息。如果消息队列为空调用 epoll_wait 使线程进入到阻塞态让出 CPU 调度。 从 Java 到 Native 整个调用流程大致是这样的 Looper#loop()- MessageQueue#next()- MessageQueue#nativePollOnce()- NativeMessageQueue#pollOnce() //注意进入 Native 层- Looper#pollOnce()- Looper#pollInner()- epoll_wait()消息的发送/唤醒机制 好现在的消息队列里面是空的并且经过上一小节的分析后我们发现用户线程阻塞到了 native 层的 Looper#pollInner() 方法我们来向消息队列发送一条消息唤醒它。 前面我们说了Java 和 Native 都各自维护了一套消息队列所以他们发送消息的入口也不一样 Java 开发使用 Handler#sendMessage() / post()C/C 开发使用 Looper#sendMessage()。 我们先来看 Java /frameworks/base/core/java/android/os/Handler.java class Handler {boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {msg.target this;return queue.enqueueMessage(msg, uptimeMillis);} }/frameworks/base/core/java/android/os/MessageQueue.java class MessageQueue {boolean enqueueMessage(Message msg, long when) {//...按照到期时间将消息插入消息队列if (needWake) {nativeWake(mPtr);}}}在使用 Handler 发送消息时不管调用的是 sendMessage 还是 post最后都是调用到 MessageQueue#enqueueMessage() 方法将消息入列入列的顺序是按照执行时间先后排序。 如果我们发送的消息需要马上被执行那么将 needWake 变量置为 true接着使用 nativeWake() 唤醒线程。 注nativeWake() 方法也是 jni 调用经过层层转发最终调用到 Native Looper 中的 wake() 方法整个转发过程的调用链清晰而且非常简单这里就不展开分析了。 Java 发送消息的方式聊完了然后我们看 Native 层如何发送消息 /system/core/libutils/Looper.cpp class looper {void Looper::sendMessageAtTime(uptime, handler,message) {int i 0;int messageCount mMessageEnvelopes.size();while (i messageCount uptime mMessageEnvelopes.itemAt(i).uptime) {i 1;}mMessageEnvelopes.insertAt(messageEnvelope(uptime, handler, message), i, 1);// Wake the poll loop only when we enqueue a new message at the head.if (i 0) {wake();}} }看上面的代码Native 层通过 sendMessageAtTime() 方法向消息队列发送消息添加消息的处理逻辑和 Java 处理逻辑类似 按照时间的先后顺序添加到 mMessageEnvelopes 集合中执行时间离得最近的消息被放在前面如果发现需要唤醒线程则调用 wake() 方法。 好Java 和 Native 发送消息的方式都介绍完了。 我们发现虽然它俩 发消息的方式 、消息类型 、 送达的消息队列 都不相同但是当需要唤醒线程时Java 和 Native 都会执行到 Looper#wake() 方法。 之前我们说 “Handler 机制的底层是 epoll eventfd”读者朋友不妨大胆猜一下这里的线程是怎么被唤醒的 /system/core/libutils/Looper.cpp class looper {void Looper::wake() {int inc 1;write(mWakeEventFd, inc);} }答案非常简单write() 一行方法调用向 mWakeEventFd 写入了一个 1小提示mWakeEventFd 的类型是 eventfd 。 为什么 mWakeEventFd 写入了一个 1线程就可以被唤醒呢 mWakeEventFd 被写入值后状态会从 不可读 变成 可读内核监听到 fd 的可读写状态发生变化会将事件从内核返回给 epoll_wait() 方法调用 而 epoll_wait() 方法一旦返回阻塞态将会被取消线程继续向下执行。 好我们来总结一下 消息的发送与唤醒 中几个关键的步骤 Java 层发送消息调用 MessageQueue#enqueueMessage() 方法如果消息需要马上执行那么调用 nativeWake() 执行唤醒Native 层发送消息调用 Looper#sentMessageAtTime() 方法处理逻辑与 Java 类似如果需要唤醒线程调用 Looper#wake()Looper#wake() 唤醒方法很简单向 mWakeEventFd 写入 1初始化队列 时为 mWakeEventFd 注册了 epoll 监听所以一旦有来自于 mWakeEventFd 的新内容 epoll_wait() 阻塞调用就会返回这里就已经起到了唤醒队列的作用 呼 到这里 消息的发送与唤醒 的流程基本上结束了接下来是 Handler 的重头戏线程唤醒后的消息分发处理 唤醒后消息的分发处理 线程在没有消息需要处理时会阻塞在 Looper 中的 pollInner() 方法调用线程唤醒以后同样也是在 pollInner() 方法中继续执行。 线程醒来以后先判断自己为什么醒过来再根据唤醒类型执行不同的逻辑。 pollInner() 方法稍微有点长大致可以分为5步来看我们一点点来捋 /system/core/libutils/Looper.cpp class looper {int pollInner(int timeoutMillis){int result POLL_WAKE;// step 1epoll_wait 方法返回int eventCount epoll_wait(mEpollFd, eventItems, timeoutMillis); if (eventCount 0) { // 事件数量为0表示达到设定的超时时间result POLL_TIMEOUT;}for (int i 0; i eventCount; i) {if (eventItems[i] mWakeEventFd) {// step 2 清空 eventfd使之重新变为可读监听的 fdawoken();} else {// step 3 保存自定义fd触发的事件集合mResponses.push(eventItems[i]);}}// step 4 执行 native 消息分发while (mMessageEnvelopes.size() ! 0) {if (messageEnvelope.uptime now) { // 检查消息是否到期messageEnvelope.handler-handleMessage(message);}}// step 5 执行 自定义 fd 回调for (size_t i 0; i mResponses.size(); i) {response.request.callback-handleEvent(fd, events, data);}return result;}void awoken() {read(mWakeEventFd) ;// 重新变成可读事件}}step 1 epoll_wait 方法返回说明有事件发生返回值 eventCount 是发生事件的数量。如果为0表示达到设定的超时时间下面的判断逻辑都不会走不为0那么我们开始遍历内核返回的事件集合 eventItems根据类型执行不同的逻辑。 step 2 如果事件类型是消息队列的 eventfd 说明有人向消息队列提交了需要马上执行的消息我们只需把消息队列的 eventfd 数据读出来使他重新变成可以触发 可读事件 的 fd然后等待方法结束就行了。 step 3 事件不是消息队列的 eventfd 说明有其他地方注册了监听 fd那么我们将发生的事件保存到 mResponses 集合中待会需要对这个事件做出响应通知注册对象。 step 4 遍历 Native 的消息集合 mMessageEnvelopes检查每个消息的到期时间如果消息到期了交给 handler 执行分发分发逻辑参考 Java Handler。 step 5 遍历 mResponses 集合把其他地方注册的 自定义 fd 消费掉响应它们的回调方法。 唤醒后执行的逻辑还是非常复杂的我们总结一下 用户线程被唤醒后优先分发 Native 层的消息紧接着通知 自定义 fd 发生的事件如果有的话最后 pollInner() 方法结束返回到 Java 层 Looper#loop() 方法执行到 Java 层的消息分发。只有当 Java Handler 执行完消息分发一次 loop() 循环才算是完成。 再之后因为 Looper#loop() 是死循环所以会马上再一次进入循环继续调用 next() 方法获取消息、阻塞到 pollInner() 、从 pollInner() 唤醒执行分发执行结束接着进入下一次循环无尽的轮回。 main 线程的一生都将重复这一流程直到 APP 进程结束运行... 总结 以上就是 Handler Native 篇的全部内容主要介绍了 Java MessageQueue 中几个关键的 jni 方法在底层是如何实现的。 将全部的代码逻辑分析完以后我们会发现 Native Handler 的实现不算复杂关键的阻塞与唤醒部分是借助了 Linux 系统 epoll 机制来实现的。 所以我们只要理解了 epoll 机制再对照源码看看 Looper#pollInner() 中的内部逻辑就能明白整个 Handler 机制是怎么一回事了。 希望对大家有帮助。

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

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

相关文章

洛谷P10288 [GESP样题 八级] 区间

原题 题目描述 小杨有一个长度为 \(n\) 的正整数序列 \(A\)。 小杨有 \(q\) 次询问。第 \(i\) 次(\(1\le i\le q\))询问时,小杨会给出 \(l_i,r_i,x_i\),请你求出 \(x_i\) 在 \(A_{l_i}, A_{l_i+1}, \dots A_{r_i}\…

百度如何搜索网址网站推广优化趋势

1. nuScenes 数据集 1.1 概述 nuScenes 数据集 (pronounced /nu:ːsiː:nz/) 是由 Motional (以前称为 nuTonomy) 团队开发的自动驾驶公共大型数据集。nuScenes 数据集的灵感来自于开创性的 KITTI 数据集。 nuScenes 是第一个提供自动驾驶车辆整个传感器套件 (6 个摄像头、1 …

AI 时代下,开发流程的重塑:从“代码先行”到“文档驱动”

本文探讨了AI编程工具在提升效率的同时,因缺乏顶层设计而导致项目混乱的困境。并提出一种“文档驱动”的AI原生开发新范式,强调高质量、结构化的文档是驾驭AI编码,实现高质量交付的关键。文章标题 引言:AI 编程工具…

P13617 [ICPC 2025 APC] Bit Counting Sequenc

题意:给定长度 $n \leq 5 \times 10^5$ 的 popcount 序列 $\{a_i\}$,求其对应的原序列。思路:观察发现 popcount 序列具有倍增构造性质,将原序列 $[0,2^k - 1]$ 的第 $k$ 位改成 $1$ 可得到 $[2^k,2^{k + 1} - 1]$…

perl -MCPAN -e install GD;

001、 Package gdlib was not found in the pkg-config search path.Perhaps you should add the directory containing `gdlib.pcto the PKG_CONFIG_PATH environment variableNo package gdlib found

Day 02 HTML的基础 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

如何在网站添加代码大气精美网站设计工作室织梦模板

【芯片DFX】万字长文带你搞懂JTAG的门门道道【芯片DFX】ARM:CoreSight、ETM、PTM、ITM、HTM、ETB等常用术语解析

网络建站的费用微网站开发一般费用多少钱

Navicat Premium(16.3.3 Windows 版或以上)正式支持 GaussDB 分布式数据库。GaussDB 分布式模式更适合对系统可用性和数据处理能力要求较高的场景。Navicat 工具不仅提供可视化数据查看和编辑功能,还提供强大的高阶功能(如模型、结…

什么网站专做店铺wordpress 一栏主题

首先已经创建好了 Vue 框架,安装好了 node.js。 没有完成的可按照此博客搭建:搭建Vue项目 之后打开终端,使用命令。 1、命令安装 axios 和 vue-axios npm install axios --save npm install vue-axios --save2、package.json 查看版本 在 p…

做静态网站的步骤怎么下载网页视频到本地

一、类型转换 C语言中的类型转换比较松散,C新增4个类型转换运算符,更加严格的显示类型转换,使转换的效率更加规范 1、static_cast static_cast,用于仅在编译时检查的强制转换。 如果编译器检测到你尝试在完全不兼容的类型之间强制…

微信公众号手机网站做网站有哪些需求

在工作中,偶尔看到有些机器的网口名字是以ethX命令,有些则以enpXsX这种名字命名。网上的资料说的都不太明白,资料也无据可查,很难让人信服。于是决定自己查了下官方的资料和源码,把这些搞清楚。 官方文档:Predictable…

P3959 [NOIP 2017 提高组] 宝藏 题解

link 题目要求任选图中一点为根,通过拓展道路最终形成一棵树,使得代价总和最小,代价受深度和边权两个因素影响。 容易想到一种爆搜,任选一点为根,每次扫描已选点来不断尝试拓展道路,但这样做太蛋疼了,我们尝试优…

(二)若依前后端分离版本二次开发 代码生成、目录添加、数据字典维护

(二)若依前后端分离版本二次开发 代码生成、目录添加、数据字典维护一 摘要 主要介绍添加目录、菜单、代码自动生成等功能。 二 目标 2.1 掌握添加目录,菜单 2.2 掌握添加数据字典 2.3 掌握代码生成 三 实施 已标签…

C#与Access数据库操作简易指南:增删改查及类封装

简介:C#是面向对象的编程语言,常用于Windows应用开发,而Microsoft Access是一种数据库管理系统。本教程指导如何结合C#操作Access数据库进行基本的增删改查(CRUD)操作,使用ADO.NET通过OLEDB类连接和操作数据库。…

对之前部署hbase总结

部署路程为看黑马大数据视频 部署直到yarn集群部署之后看尚硅谷的视频完成部署即可 之后参考有可能会报错直接复制报错到csdn即可 启动代码和停止指令: 注意每次启动检查每一个主机启动是否完成 慢一些 否则会报错

网站排版图片网站禁止右键

一、前言 在大多数传统的web系统中,使用Redis一般都是作为缓存使用,在大数据查询时作为缓解性能的一种解决方案。博主的的系统中使用Redis也主要使用到缓存的作用,还有做了注册中心,分布式事务。其他的强大的功能,没有…

书画工作室网站模板网站建设做vip视频网站赚钱吗

在K8s中,创建Pod时的流程如下: 用户通过Kubectl或其他方式向API Server发送创建Pod的请求。API Server接收到请求后,会先进行权限验证和身份认证。一旦验证通过,API Server会将请求转发给Scheduler组件。Scheduler负责对新创建的…

网站自动更新时间代码网站域名和空间费用

网站地址&#xff1a;网络游戏防沉迷实名认证系统 PHP代码&#xff1a; 创建对应文件&#xff0c;在需要的位置get传参请求即可&#xff0c;具体参数参考 网络游戏防沉迷实名认证系统接口对接技术规范v2.0 1、上传信息 <?php $url "https://wlc.nppa.gov.cn/test…

百度推广要自己建站吗做网站需要公章吗

我们使用redis时发现yaml配置中的redis相关配置不生效&#xff0c;后面发现将配置修改甚至删除所有相关redis的配置&#xff0c;springboot依然能使用redis里面默认的db0并且不报错。上网查阅了一些文章&#xff0c;也都没有解决今天分享下&#xff0c;我的处理方法, SpringBo…