【QT八股文】系列之篇章3 | QT的多线程以及QThread与QObject
【QT八股文】系列之篇章3 | QT的多线程
- 前言
- 4. 多线程
- 为什么需要使用线程池
- 线程池的基础知识
- python中创建线程池的方法
- 使用threading库+队列Queue来实现线程池
- 使用threadpool模块,这是个python的第三方模块,支持python2和python3
- QThread的定义
- QT多线程知识点
- 怎么做多线程(原理篇)
- 方案1:信号与线程
- 方案2:线程
- 方案3:线程与队列
- QT多线程的使用方法(具体方法篇)
- QT 多线程/QT线程同步的方法
- 5. QThread与QObject
- QThread的定义
- 对QObject的理解
- Q_OBJECT的作用是什么,内部实现了些什么
- QObject是否是线程安全的/线程依附性是否可以改变/如何安全调用
- 下一章笔记
- 说明
前言
- 第一篇章主要是基础定义及QT中重要的事件机制
笔记链接:【QT八股文】系列之篇章1 | QT的基础知识及事件/机制 - 第二篇章主要是QT的信号与槽以及通讯流程
笔记链接:【QT八股文】系列之篇章2 | QT的信号与槽及通讯流程
这里我们主要件点更实际的,也就是多线程以及QThread与QObject
因为介绍到信号与槽,所以笔者我会讲通讯流程提前在前面来介绍
原创文章,未经同意请勿转载
4. 多线程
为什么需要使用线程池
- 减少系统开销:频繁创建/销毁线程的开销大,影响处理效率。而在线程池缓存线程可用已有的闲置线程来执行新任务,避免了创建/销毁带来的系统开销。
- 避免阻塞问题:线程并发数量过多,抢占系统资源从而导致阻塞。线程能共享系统资源,如果同时执行的线程过多,就有可能导致系统资源不足而产生阻塞的情况。
- 管理和控制线程:运用线程池可以进行多线程的调度,有利于延迟执行,优先级执行和定时循环执行策略
线程池的基础知识
这里必须要知道线程池实现主要依靠两个部分,一个是任务队列,另外一个是线程的管理控制中心
很明显。任务队列的数据结构就是队列,先进先出,用Queue模块实现,那先了解一下Queue:
- Queue的常用方法
- Queue.qsize():返回queue的大小。
- Queue.empty():判断队列是否为空,通常不太靠谱。
- Queue.full():判断是否满了。
- Queue.put(item, block=True, timeout=None): 往队列里放数据。
- Queue.put_nowait(item):往队列里存放元素,不等待
- Queue.get(item, block=True, timeout=None): 从队列里取数据。
- Queue.get_nowait(item):从队列里取元素,不等待
- Queue.task_done():表示队列中某个元素是否的使用情况,使用结束会发送信息。
- Queue.join():一直阻塞直到队列中的所有元素都执行完毕。
python中创建线程池的方法
这里必须要知道线程池实现主要依靠两个部分,一个是任务队列,另外一个是线程的管理控制中心
- 使用threading库+队列Queue来实现线程池
- 使用threadpool模块,这是个python的第三方模块,支持python2和python3
- 使用concurrent.futures模块,这个模块是python3中自带的模块,python2.7以上版本也可以安装使用
使用threading库+队列Queue来实现线程池
1、创建一个 Queue.Queue() 的实例,然后使用数据对它进行填充。
2、将经过填充数据的实例传递给线程类,后者是通过继承threading.Thread 的方式创建的。
3、生成守护线程池。
4、每次从队列中取出一个项目,并使用该线程中的数据和 run 方法以执行相应的工作。
5、在完成这项工作之后,使用 queue.task_done() 函数向任务已经完成的队列发送一个信号。
6、对队列执行 join 操作,实际上意味着等到队列为空,再退出主程序。
在使用这个模式时需要注意一点:通过将守护线程设置为 true,程序运行完自动退出。好处是在退出之前,可以对队列执行 join 操作、或者等到队列为空。
-
代码
import Queue import threading import time queue = Queue.Queue() class ThreadNum(threading.Thread):def __init__(self, queue):threading.Thread.__init__(self)self.queue = queuedef run(self):while True:#消费者端,从队列中获取numnum = self.queue.get()print("Retrieved", num)time.sleep(1) #在完成这项工作之后,使用 queue.task_done() 函数向任务已 经完成的队列发送一个信号self.queue.task_done()print("Consumer Finished") def main():#产生一个 threads pool, 并把消息传递给thread函数进行处理,这 里开启10个并发for i in range(5):t = ThreadNum(queue)t.setDaemon(True)t.start()#往队列中填数据for num in range(10):queue.put(num)#wait on the queue until everything has been processedqueue.join()if __name__ == '__main__':main()time.sleep(500) 输出为: ('Retrieved', 0) ('Retrieved', 1) ('Retrieved', 2) ('Retrieved', 3) ('Retrieved', 4) ('Retrieved', 5) ('Retrieved', 6) ('Retrieved', 7) ('Retrieved', 8) ('Retrieved', 9)
注意运行main函数后继续执行time.sleep(500),可以观察到主线程未结束的情况下ThreadNum(queue)生成的线程还在运行。如果需要停止线程的话可以对以上代码加以修改
-
代码
import Queue import threading import time queue = Queue.Queue() class ThreadNum(threading.Thread):"""没打印一个数字等待1秒,并发打印10个数字需要多少秒?"""def __init__(self, queue):threading.Thread.__init__(self)self.queue = queuedef run(self):done = Falsewhile not done:#消费者端,从队列中获取numnum = self.queue.get()if num is None:done = Trueelse:print("Retrieved", num)time.sleep(1) #在完成这项工作之后,使用 queue.task_done() 函数向任务已 经完成的队列发送一个信号self.queue.task_done()print("Consumer Finished") def main():#产生一个 threads pool, 并把消息传递给thread函数进行处理,这 里开启10个并发for i in range(5):t = ThreadNum(queue)t.setDaemon(True)t.start()#往队列中填错数据for num in range(10):queue.put(num)queue.join()time.sleep(100)for i in range(10):queue.put(None)print('None')time.sleep(200)if __name__ == '__main__':start = time.time()main()print"Elapsed Time: %s" % (time.time() - start)
main函数执行完后队列向线程发送None消息,触发线程的停止标识,这样就可以动态管理线程池了。
使用threadpool模块,这是个python的第三方模块,支持python2和python3
QThread的定义
QThread 是 QT 中用于创建线程的类,它提供了一组方法用于启动、停止、监测线程的运行状态,以及获取线程的相关信息。
QThread 类包含了多个方法,用于启动、停止、监测线程的运行状态,以及获取线程的相关信息。其中:
run()
方法启动线程的执行stop()
方法停止线程的执行join()
方法等待线程的执行完毕detach()
方法将线程从事件循环中移除。
此外,setName()
、setId()
、setPriority()
、getPriority()
、setSignalsBlocked()
、isSignalsBlocked()
等方法用于修改线程的属性。
QT多线程知识点
多线程运行机制:当启动多线程后,注册信号,槽函数为主线程中的函数,当任务完成后,发射信号,在主线程中对UI进行更新。【QThred】
怎么做多线程(原理篇)
方案1:信号与线程
程序启动,创建一个线程(存活周期:直到软件关闭),当点击事件发生,发送信号,该信号连接两个槽,A负责界面变化切换,B进行后台通讯,B通讯结束,再通过信号将结果返回到界面切换,通过这种机制实现界面与通信的分离。
💡 结论:
经过代码测试,发现这个方案并非是异步的,而是同步的,原因是同时连接两个槽,这个槽机制应该是一个列表,串行执行的,必然两个槽的执行会存在先后问题,当一个阻塞,另一个也就阻塞了。
方案2:线程
程序启动,当点击事件发生,发送信号,该信号连接一个槽,槽负责界面变化切换,同时创建一个线程(存活周期:报文发送接收完成既关闭),线程进行后台通讯,通讯结束,再通过信号将结果返回到界面切换,通过这种机制实现界面与通信的分离。线程中发送的数据要通过线程创建时传入。
💡 结论:
该方法虽然实现了界面切换与通讯的异步处理,但是每点击一次按钮,都需要一次线程的创建,而且对于一直保持通讯的心跳机制,还需要单独起一个线程,可谓是花费巨大,感觉不是很好的方法
方案3:线程与队列
为了解决方案2中频繁创建线程的问题,现在做如下改进,程序启动,创建一个线程(存活周期:直到软件关闭),在线程中创建多个队列,线程监控队列,队列分别有信号队列,信息发送队列,当前界面位置队列,当界面事件发生,去修改队列,线程则监控队列,取出队列进行处理,处理之后将结果返回
💡 结论:
这样的处理机制避免了线程的频繁创建,同时能存储一些全局的重要信息,也实现了异步的效果。
QT多线程的使用方法(具体方法篇)
-
方法一:利用python的threading库实现(主要使用threading.Thread类)
- 线程启动使用start()函数
- 如果需要等待线程执行使用join,这样主线程会阻塞
💡 使用join方法会让主线程阻塞在这里,等待子线程结束,在里面可以设置阻塞的时间
-
方法二:继承QThread,并重写run函数
使用QThread类来创建和管理多线程。具体步骤包括:继承QThread类并重写其run()函数,将需要在子线程中执行的代码放入run()函数中【保证线程安全】;在主线程中创建QThread对象,将其指针作为参数传递给需要在子线程中执行的对象;调用QThread对象的start()函数来启动子线程。在线程任务执行过程中,可以使用 QThread 的 join() 方法等待线程执行完毕。① 创建一个类从QThread类派生
② 在子线程类中重写 run 函数, 将处理操作写入该函数中
③ 在主线程中创建子线程对象, 启动子线程, 调用start()函数
💡 需要注意的事项:如果是while循环,想要结束线程,调用QThread::quit是没有用,因为这样的线程根本就不需要事件循环,比较好的方法就是把while内的控制变量设置为false或者直接使用Qt很不推荐的方法QThread::terminate。terminate()强制退出。
-
方法三:使用线程池
QtConcurrent运行一个线程池,它是一个更高级别的API,不适合运行大量的阻塞操作;如果你做了很多阻塞操作,你很快就会耗尽池并让其他请求排队,在那种情况下,QThread(较低级别的构造)可能更适合于操作(每个代表一个线程)。
-
方法四:利用QRunnable 类
QRunnable 类是 PyQt5 中的可运行对象类,它提供了 run() 方法来执行线程,并可以通过 QRunnableInterface 实现线程通信。QRunnable 类创建线程的基本原理是创建一个 QRunnable 实例,并将其作为参数传递给 QApplication 的 thread() 方法创建线程。在线程任务执行过程中,可以使用 QRunnable 的 run() 方法执行线程任务。QRunnable 对象可以访问主线程的 QCoreApplication 对象。在 QRunnable 对象中,需要使用 start() 方法启动线程,并使用 join() 方法等待线程执行完毕。
-
方法五:继承QObject,并将对象移动至子线程(&QThread)
① 将业务处理抽象成一个业务类, 在该类中创建一个业务处理函数
② 在主线程中创建一QThread类对象
③ 在主线程中创建一个业务类对象
④ 将业务类对象移动到子线程中
⑤ 在主线程中启动子线程
⑥ 通过信号槽的方式, 执行业务类中的业务处理函数
💡 多线程使用注意事项:
-
业务对象, 构造的时候不能指定父对象
-
子线程中不能处理ui窗口(ui相关的类)
-
子线程中只能处理一些数据相关的操作, 不能涉及窗口
-
QT 多线程/QT线程同步的方法
- 使用 QMutex 对象:QMutex 是 QT 中用于线程同步的同步原语。每个线程都可以访问一个 QMutex 对象,通过 lock() 和 unlock() 方法实现线程同步。当一个线程需要访问共享资源时,它会首先尝试获取 QMutex 对象的锁,如果锁已经被其他线程获取了,那么该线程将被阻塞,直到锁被释放。
- 使用 QSemaphore 对象:QSemaphore 是 QT 中用于线程同步的同步原语。每个线程都可以访问一个 QSemaphore 对象,通过 semaphore.wait() 和 semaphore.signal() 方法实现线程同步。当一个线程需要访问共享资源时,它会首先尝试等待 QSemaphore 对象的许可,如果许可已经被其他线程获取了,那么该线程将被阻塞。
- 使用 QWaitCondition 对象:QWaitCondition 是 QT 中用于线程同步的同步原语。它结合了 QMutex 和 QSemaphore 的特点,可以更方便地实现线程同步。QWaitCondition 对象包含一个互斥锁和一个信号槽,当一个线程需要等待条件满足时,它会挂起并等待互斥锁的释放,当条件满足时,该线程会被唤醒并执行相应的操作。
- 使用 QEventLoop 对象:QEventLoop 是 QT 中用于处理事件循环的类,它可以实现线程同步。每个线程都可以创建一个 QEventLoop 对象,当线程需要访问共享资源时,它会进入 QEventLoop 对象的 eventLoop() 方法,等待事件处理完毕再继续执行。
- QReadWriteLock类
》一个线程试图对一个加了读锁的互斥量进行上读锁,允许;
》一个线程试图对一个加了读锁的互斥量进行上写锁,阻塞;
》一个线程试图对一个加了写锁的互斥量进行上读锁,阻塞;、
》一个线程试图对一个加了写锁的互斥量进行上写锁,阻塞。
读写锁比较适用的情况是:需要多次对共享的数据进行读操作的阅读线程。
QReadWriterLock 与QMutex相似,除了它对 “read”,"write"访问进行区别对待。它使得多个读者可以共时访问数据。使用QReadWriteLock而不是QMutex,可以使得多线程程序更具有并发性。 - 信号量QSemaphore
但是还有些互斥量(资源)的数量并不止一个,比如一个电脑安装了2个打印机,我已经申请了一个,但是我不能霸占这两个,你来访问的时候如果发现还有空闲的仍然可以申请到的。于是这个互斥量可以分为两部分,已使用和未使用。 - QReadLocker便利类和QWriteLocker便利类对QReadWriteLock进行加解锁
5. QThread与QObject
QThread的定义
QThread 是 QT 中用于创建线程的类,它提供了一组方法用于启动、停止、监测线程的运行状态,以及获取线程的相关信息。
QThread 类包含了多个方法,用于启动、停止、监测线程的运行状态,以及获取线程的相关信息。其中:
run()
方法启动线程的执行stop()
方法停止线程的执行join()
方法等待线程的执行完毕detach()
方法将线程从事件循环中移除。
此外,setName()
、setId()
、setPriority()
、getPriority()
、setSignalsBlocked()
、isSignalsBlocked()
等方法用于修改线程的属性。
对QObject的理解
- Q_OBJECT 是 Qt 框架中的一个宏定义,用于在类的声明中标记该类需要使用 Qt 的元对象系统(Meta-Object System)。使用 Q_OBJECT 宏定义后,编译器会在编译期自动生成元对象代码,包括信号(signal)和槽(slot)的注册、元对象信息的注册等等。
- QObject 类是Qt 所有类的基类。
- QObject是Qt对象模型的核心。这个模型的中心要素就是一种强大的叫做信号与槽无缝对象沟通机制。你可以用 connect() 函数来把一个信号连接到槽,也可以用disconnect() 函数来破坏这个连接。为了避免永无止境的通知循环,你可以用blockSignal() 函数来暂时阻塞信号。保护函数 connectNotify() 和 disconnectNotify() 可以用来跟踪连接。
对象树都是通过QObject 组织起来的,当以一个对象作为父类创建一个新的对象时,这个新对象会被自动加入到父类的 children() 队列中。这个父类有子类的所有权。能够在父类的析构函数中自动删除子类。可以通过findChild()和findChildren() 函数来寻找子类。
每个对象都一个对象名称objectName() ,而且它的类名也可以通过metaObject()函数。你可以通过inherits() 函数来决定一个类是否继承其他的类。当一个对象被删除时,它会发射destory() 信号,你可以抓住这个信号避免某些事情。
对象可以通过event() 函数来接收事情以及过滤来自其他对象的事件。就好比installEventFiter() 函数和eventFilter() 函数。childEvent() 函数能够重载实现子对象的事件。
QObject还提供了基本的时间支持,QTimer类 提高了更高层次的时间支持。
任何对象要实现信号与槽机制,Q_OBJECT 宏都是强制的。你也需要在源原件上运行元对象编译器。不管是否真正用到信号与槽机制,最好在所有QObject子类使用Q_OBJECT宏,以避免出现一些不必要的错误。
所有的Qt widgets 都是基础QObject。如果一个对象是widget,那么isWidgetType()函数就能判断出。
Q_OBJECT的作用是什么,内部实现了些什么
Q_OBJECT 是 Qt 框架中的一个宏定义,用于在类的声明中标记该类需要使用 Qt 的元对象系统(Meta-Object System)。使用 Q_OBJECT 宏定义后,编译器会在编译期自动生成元对象代码,包括信号(signal)和槽(slot)的注册、元对象信息的注册等等。
具体来说,使用 Q_OBJECT 宏定义后,编译器会为该类生成一个 QMetaObject 对象,该对象包含了该类的元对象信息,包括类名、信号和槽的名称、参数类型等等。这些信息可以通过 QObject::metaObject() 函数获取到。
此外,使用 Q_OBJECT 宏定义后,还可以在该类中使用信号和槽,使用 emit 关键字来发射信号,使用 connect 函数将信号和槽连接起来。这些功能都是通过 Qt 的元对象系统实现的。
需要注意的是,使用 Q_OBJECT 宏定义的类必须直接或间接继承自 QObject 类。
- 实现原理
Q_OBJECT 宏定义会为该类自动添加一些成员变量和成员函数,用于支持 Qt 的元对象系统。
1、 QObject 类的虚函数 metaObject(),它返回一个描述该对象的元对象。
2、QMetaObject 类型的静态变量,用于存储该对象的元对象。
QObject是否是线程安全的/线程依附性是否可以改变/如何安全调用
- QObject及其所有子类都不是线程安全的(但都是可重入的)。因此,你不能有两个线程同时访问一个QObject对象,除非这个对象的内部数据都已经很好地序列化(例如为每个数据访问加锁)。
- 可以改变QObject的线程依附性。 调用QObject::moveToThread()函数。该函数会改变一个对象及其所有子对象的线程依附性。
- 如何安全的在另外一个线程中调用QObject对象的接口
- 多线程机制设计
- 将事件提交到接收对象所在线程的事件循环;当事件发出时,响应函数就会被调用。
下一章笔记
下篇笔记链接:【QT的性能优化及异常处理】
下篇笔记主要内容:【待更新】
说明
码字不易,可能当中存在某些字体错误(笔者我没有发现),如果有错误,欢迎大家指正。🤗
另外因为笔记是之前做的,这里我只把我之前做的搬移和重新排版过来,如果有知识上的错误也欢迎大家指正。
相关文章:

【QT八股文】系列之篇章3 | QT的多线程以及QThread与QObject
【QT八股文】系列之篇章3 | QT的多线程 前言4. 多线程为什么需要使用线程池线程池的基础知识python中创建线程池的方法使用threading库队列Queue来实现线程池使用threadpool模块,这是个python的第三方模块,支持python2和python3 QThread的定义QT多线程知…...

基于python flask的web服务
基本例子 from flask import Flask app Flask(__name__) app.route(/)#检查访问的网址,根路径走这里 def hello_world():return hello world#返回hello worldif __name__ __main__:# 绑定到指定的IP地址和端口app.run(host0.0.0.0, port1000, debugTrue)##绑定端…...

HTTP 响应分割漏洞
HTTP 响应分割漏洞 1.漏洞概述2.漏洞案例 1.漏洞概述 HTTP 响应拆分发生在以下情况: 数据通过不受信任的来源(最常见的是 HTTP 请求)进入 Web 应用程序。该数据包含在发送给 Web 用户的 HTTP 响应标头中,且未经过恶意字符验证。…...

Algoriddim djay Pro Ai for Mac:AI引领,混音新篇章
当AI遇上音乐,会碰撞出怎样的火花?Algoriddim djay Pro Ai for Mac给出了答案。这款专业的DJ混音软件,以AI为引擎,引领我们进入混音的新篇章。 djay Pro Ai for Mac的智能混音功能,让每一位DJ都能感受到前所未有的创作…...

常见算法(3)
1.Arrays 它是一个工具类,主要掌握的其中一个方法是srot(数组,排序规则)。 o1-o2是升序排列,o2-o1是降序排列。 package test02; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparat…...

集中抄表电表是什么?
1.集中抄表电表:简述 集中抄表电表,又称为远程抄表系统,是一种现代化电力计量技术,为提升电力行业的经营效率和客户服务质量。它通过自动化的形式,取代了传统人工抄水表,完成了数据信息实时、精确、高效率…...

第八届能源、环境与材料科学国际学术会议(EEMS 2024)
文章目录 一、重要信息二、大会简介三、委员会四、征稿主题五、论文出版六、会议议程七、出版信息八、征稿编辑 一、重要信息 会议官网:http://ic-eems.com主办方:常州大学大会时间:2024年06月7-9日大会地点:新加坡 Holiday Inn …...

09.自注意力机制
文章目录 输入输出运行如何运行解决关联性attention score额外的Q K V Multi-head self-attentionPositional EncodingTruncated Self-attention影像处理vs CNNvs RNN图上的应用 输入 输出 运行 链接(Attention Is All You Need) 如何运行 解决关联性 a…...

时政|杂粮产业
政策支持 《新一轮千亿斤粮食产能提升行动方案(2024—2030年)》明确,按照“巩固提升口粮、主攻玉米大豆、兼顾薯类杂粮”的思路,因地制宜发展马铃薯、杂粮杂豆等品种,根据市场需求优产稳供。 产地发展 河北省石家庄…...

docker 安装 私有云盘 nextcloud
拉取镜像 # 拉取镜像 sudo docker pull nextcloud运行nextcloud 容器 # 内存足够可以不进行内存 --memory512m --memory-swap6g # 桥接网络 --network suixinnet --network-alias nextcloud \ sudo docker run -itd --name nextcloud --restartalways \ -p 9999:80 \ -v /m…...

第十一届蓝桥杯物联网试题(国赛)
国赛题目看着简单其实还是挺复杂的,所以说不能掉以轻心,目前遇到的问日主要有以下几点: 本次题主要注重的是信息交互,与A板通信的有电脑主机和B板,所以处理好这里面的交互过程很重要 国赛中避免不了会收到其他选手的…...

算法金 | Dask,一个超强的 python 库
本文来源公众号“算法金”,仅用于学术分享,侵权删,干货满满。 原文链接:Dask,一个超强的 python 库 1 Dask 概览 在数据科学和大数据处理的领域,高效处理海量数据一直是一项挑战。 为了应对这一挑战&am…...

Java 说唱歌手
Yo yo yo,欢迎来到Java地带,技术的盛宴开启, 从JDK到JVM,我们构建的是数字世界的奇迹。 Spring Boot启动,微服务架构轻盈起舞, IoC解耦依赖,AOP切面如丝般顺滑。 Maven管理依赖,Gra…...

面试-软件工程与设计模式相关,Spring简介
面试-软件工程与设计模式相关,Spring简介 1.编程思想1.1 面向过程编程1.2 面向对象编程1.2.1 面向对象编程三大特征 1.3 面向切面编程1.3.1 原理1.3.2 大白话?1.3.3 名词解释1.3.4 实现 2. 耦合与内聚2.1 耦合性2.2 内聚性 3. 设计模式3.1 设计模型七大原…...

IDEA中一些常见操作【持续更新】
文章目录 前言善用debugidea中debug按钮不显示自动定位文件【始终选择打开的文件】idea注释不顶格【不在行首】快速定位类的位置【找文件非常快】创建文件添加作者及时间信息快速跳转到文件顶端 底端 前言 因为这些操作偶尔操作一次,不用刻意记忆,有个印…...

java继承使用细节二
构造器 主类是无参构造器时会默认调用 public graduate() {// TODO Auto-generated constructor stub也就是说我这里要用构造器会直接调用父类。它是默认看不到的 ,System.out.println("graduate");} 但当主类是有参构造器如 public father_(int s,doubl…...

c++11 标准模板(STL)本地化库 - 平面类别(std::numpunct_byname) 表示系统提供的具名本地环境的 std::numpunct
本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析,以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 表示系统提供的具名本地环境的 std::numpunct std::numpunct_byn…...

XILINX FPGA DDR 学习笔记(一)
DDR 内存的本质是数据的存储器,首先回到数据的存储上,数据在最底层的表现是地址。为了给每个数据进行存放并且在需要的时候读取这个数据,需要对数据在哪这个抽象的概念进行表述,我们科技树发展过程中把数据在哪用地址表示。一个数…...

vue源码2
vue之mustache库的机理其实是将模板字符串转化为tokens 然后再将 tokens 转化为 dom字符串,如下图 对于一般的将模板字符串转化为dom字符串,这样不能实现复杂的功能 let data {name:小王,age:18 } let templateStr <h1>我叫{{name}},我今年{{ag…...

Android四大组件 Broadcast广播机制
一 概述 广播 (Broadcast) 机制用于进程或线程间通信,广播分为广播发送和广播接收两个过程,其中广播接收者 BroadcastReceiver 是 Android 四大组件之一。BroadcastReceiver 分为两类: 静态广播接收者:通过 AndroidManifest.xm…...

redisson 使用fastJson2序列化
前因:一个项目:有人用redisTemplete存数据(使用了fastjson2),使用redisson取的时候就会报错。要让redisTemplete与redisson序列化一致 一、自定义序列化器 import com.alibaba.fastjson2.JSON; import com.alibaba.fa…...

Python数据分析常用函数
Python基础 数字处理函数 Python提供了用于数字处理的内置函数和内置模块(math),使用内置模块,需要先导入 import math。 内置函数math模块abs(-5)返回绝对值math.ceil(2.3)返回不小于x的最小整数divmod(9,4)返回商和余数math.floor(2.3)返回不大于x的…...

C++ 数据结构算法 学习笔记(32) -五大排序算法
C 数据结构算法 学习笔记(32) -五大排序算法 选择算法 如下若有多个女生的身高需要做排序: 常规思维: 第一步先找出所有候选美女中身高最高的,与最后一个数交换 第二步再找出除最后一位美女外其它美女中的最高者,与倒数第二个美女交换位置 再找出除最…...

从入门到精通:详解Linux进程管理
前言 在这篇文章中,我将带领大家深入学习和理解Linux系统中的进程管理。无论你是初学者还是有一定经验的开发者,相信这篇文章都会对你有所帮助。我们将详细讲解冯诺依曼体系结构、操作系统概念、进程管理、进程调度、进程状态、环境变量、内存管理以及其…...

【Linux】如何在 Linux 系统中使用 envsubst 来处理 Nginx 配置模板
一、创建 nginx.template 模板文件 vim nginx.template复制下面文件内容 server { listen ${BY_PORT}; server_name ${BY_HOST}; location /sys/ { proxy_pass http://${BY_GRAFANA_HOST}:${BY_GRAFANA_PORT}/; } # 其他配置... }这个模板中包含了几个环境变量&#…...

【LeetCode】438.找到字符串中所有字母异位词
找到字符串中所有字母异位词 题目描述: 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。 示…...

力扣96. 不同的二叉搜索树
Problem: 96. 不同的二叉搜索树 文章目录 题目描述思路复杂度Code 题目描述 思路 一个数字做根节点的话可能的结果为:其左边数字做子树的组合数字乘以其右边数字做子树的个数之积 1.创建备忘录memo; 2.递归分别求取当前数字左边和右边数字做子树的数量&…...

哈希表的用途
...

k8s笔记 | 高度调度
CronJob计划任务 简介:在k8s中周期性运行计划任务,与linux中的crontab相同;注意点 CornJob执行的时间是controller-manager的时间,所以一定要确保controller-manager的时间是准确的,另外cornjob cron表达式 文章参…...

Rom应用开发遇到得一些小bug
记录一些细碎得bug ROM时间类问题 问题描述: 设备拔电重启,ROM时间为默认时间如1970年1月1日,与某些业务场景互斥 问题原因: 后台接口校验https证书校验失败,要求是2年内得请求头校验了时间戳,时间戳过期…...