《Effective Objective-C》阅读笔记(下)
目录
内存管理
理解引用计数
引用计数工作原理
自动释放池
保留环
以ARC简化引用计数
使用ARC时必须遵循的方法命名规则
变量的内存管理语义
ARC如何清理实例变量
在dealloc方法中只释放引用并解除监听
编写“异常安全代码”时留意内存管理问题
以弱引用避免保留环
以“自动释放池块”降低内存峰值
用“僵尸对象”调试内存管理问题
不要使用retainCount
块与大中枢派发
理解“块”这一概念
块的基础知识
块的内部结构
全局块、栈块及堆块
为常用的块类型创建typedef
用handler块降低代码分散程度
用块引用其所属对象时不要出现保留环
多用派发队列,少用同步锁
编辑
多用GCD,少用performSelector系列方法
掌握GCD及操作队列的使用时机
通过Dispatch Group机制,根据系统资源状况来执行任务
使用dispatch_once来执行只需运行一次的线程安全代码
不要使用dispatch_get_current_queue
系统框架
熟悉系统框架
多用枚举块,少用for循环
对自定义其内存管理语义的collection使用无缝桥接
构建缓存时选用NSCache而非NSdictionary
精简initiakize与load的实现代码
别忘了NSTimer会保留其目标对象
内存管理
理解引用计数
OC使用引用计数来管理内存。
引用计数工作原理
NSObject协议声明了下面三个方法来操作计数器,以递增或递减其值:
retain 递增保留计数
release 递减保留计数
autorelease 待清理“自动释放池”,再递减保留计数
对象被创建后保留计数的变化过程如下图所示:
一般调用完release后都会清空指针,这就能保证不会出现可能指向无效对象的指针。
自动释放池
有时可以不调用release,改为调用autorelease,此方法会在稍后递减计数,通常是下一次“事件循环”时递减。
使用自动释放池autorelease可以延长对象生命期,使其在跨越方法调用边界后依然可以存活一段时间。
保留环
引用计数经常要注意的一个问题是“保留环”,“保留环”会导致内存泄漏,因为循环中的对象保留计数不会降为0,通常采用“若引用”来解决这一问题。
以ARC简化引用计数
ARC,即自动引用计数,所做的事情就是自动管理引用计数。由于ARC自动执行retain、release、autorelease等操作,所以不能调用上述方法。
ARC在调用这些方法时,并不通过消息派发机制,而是直接调用其底层C语言版本,这样性能更好。
使用ARC时必须遵循的方法命名规则
若方法名以下列词语开头,则其返回的对象归调用者所有:
若方法名不以上述四个词语开头,则表示其所返回的对象不归调用者所有。
变量的内存管理语义
在应用程序中,可用下列修饰符来改变局部变量与实例变量的语义:
通过__weak局部变量可以打破由块所引入的“保留环”。
ARC如何清理实例变量
ARC会借助OC特性来生成清理例程,来自动清理OC对象,所以ARC环境下通常无需再编写dealloc方法
不过如果有非OC的对象,那么仍然需要清理,dealloc方法可以这样写:
在dealloc方法中只释放引用并解除监听
对象在经历其生命期后,最终会为系统所回收,这时就要执行dealloc方法了。dealloc方法中要做的主要就是释放对象所拥有的引用。如果对象拥有其他非OC对象,那就要手工释放。
dealloc方法中还要把配置的观测行为清理掉,比如用NSNotificationCenter订阅的通知,dealloc可以这样写:
有一些开销较大或系统内稀缺的资源不在dealloc中释放,比如文件描述符、套接字、大块内存等。通常的做法是:实现另一个方法,当对象使用完后,就调用此方法。
这种对象所属的类,接口可以这样写:
#import <Foudation/Foudation.h>
@interface EOCServerConnection : NSObject
- (void)open:(NSString*)address;
- (void)close;
@end
该类与开发者的约定是:想打开连接,就调用“open:”方法,连接完毕就调用close方法。
close与dealloc方法可以这样写:
#import <Foudation/Foudation.h>
@interface EOCServerConnection : NSObject
- (void)open:(NSString*)address;
- (void)close;
@end
还要注意:dealloc中不要随便调用其他方法,执行异步任务的方法不应在dealloc里调用,只能在正常状态下执行的方法不应在dealloc里调用,属性的存取方法不应在dealloc里调用。
编写“异常安全代码”时留意内存管理问题
在try块中,如果先保留了某个对象,在释放它以前又抛出了异常,那么除非catch块能处理此问题,否则对象所占内存就将泄漏。
在手动管理引用计数时,要使用@finally块,并在块中释放对象,这样无论是否抛出异常,其中的代码都保证会运行且只运行一次。
当自动管理引用计数时,需要打开-fobjc-arc-exceptions标志,该标志默认关闭,只有在打开时,才会自动管理异常的引用计数,不过降低运行效率。
当遇到大量异常捕获操作时,就要考虑重构代码,用NSError式错误信息传递法来取代异常。
以弱引用避免保留环
最简单的保留环就是两个对象互相引用对方。
保留环会导致内存泄漏
如果只剩一个引用还指向保留环中的实例,而现在又把这个引用移除,那么整个保留环就泄漏了。
避免保留环最佳方式是弱引用,这种引用经常用来表示“非拥有关系”,将属性声明为unsafe_unretained或weak即可。
两者都会对属性弱引用,区别只是对象回收后的行为:
以“自动释放池块”降低内存峰值
嵌套自动释放池,可以控制应用的内存峰值,使其不致过高。
比如这段代码:
如果方法创建临时对象,那这些对象即便不再使用,也依然存活,直到系统将其释放并回收,意味着所有临时对象都要等for循环执行完才会释放。这会导致程序所占内存量持续上涨。
当循环长度取决于用户输入时更如此,比如:
这时,增加一个自动释放池,把循环内的代码包裹在“自动释放池块”中,那么循环中自动释放的对象就会放在这个池,内存峰值就会降低。
用“僵尸对象”调试内存管理问题
Cocoa提供了“僵尸对象”这一功能,当功能启用后,系统会把所有已经回收的实例转化为“僵尸对象”,而不会真正回收它们。这种对象内存不可能遭到覆写,并且收到消息后会抛出异常,准确说明发送过来的消息,并描述回收之前的那个对象。僵尸对象是调试内存管理问题的最佳方式。
将NSZombieEnabled环境变量设为YES,即可开启此功能。开启功能后,系统会修改对象的isa指针,指向特殊的僵尸类,从而使对象变为僵尸对象,他会相应所有选择子,响应方式为:打印一条包含信息内容及其接收者的消息,然后终止应用程序。
不要使用retainCount
ARC中已经废弃了retainCount这一方法,而在不启用ARC时,也不应该使用这一方法。
这个方法之所以无用,原因在于:它所返回的保留计数只是某个给定时间点上的值。
块与大中枢派发
理解“块”这一概念
块可以实现闭包
块的基础知识
块与函数类似,只不过是直接定义在另一个函数里的,和定义它的函数共享同一个范围内的东西,用符号“^”来表示,后面跟一对花括号。
块类型的语法结构如下:
块的强大之处是:在声明它的范围内,所有变量都可以为其所捕获,但是默认情况下,不可以在块里修改。
如果声明时加上__block修饰符,这样就可以在块内修改了。
如果块捕获了对象类型,就会自动保留它,就会导致一个问题,块本身也具有引用计数,这样就很容易导致循环引用。
块的内部结构
栈的内存布局如图:
这里invoke变量是个函数指针,指向块的实现代码,descriptor是指向结构体的指针,结构体中声明了块对象的总体大小,还声明了copy与dispose两个辅助函数对应的函数指针。
全局块、栈块及堆块
定义块时,所占内存区域是分配在栈中的,离开相应范围后,栈内存可能被覆写。
将块对象发送copy消息就可以拷贝,把块从栈复制到堆。此后再调用copy,只会递增块对象引用计数
除了栈块和堆块,还有全局块,这种块不会捕捉任何状态,也不需要,块所使用的内存区域在编译器就已经确定了。这种块可以声明在全局内存中,不需要在栈中创建。
全局块的拷贝是个空操作,它实际上相当于单例。
为常用的块类型创建typedef
块类型的语法结构如下:
为了简化,可以使用typedef为块起一个已读的别名,比如这样:
现在可以直接使用新类型了。
当块作为参数时,也可以简化,比如:
简化后:
使用类型定义还有个好处,就是在打算重构块时,会很方便,只要修改类型定义处即可。
用handler块降低代码分散程度
为用户界面编码时,经常异步执行任务,如果使用委托模式,那么处理数据的代码总是在受委托者处实现,如下图:
而如果改用块来写的话,代码就会变得更加清晰。
如此一来,代码就变得好懂许多了。
除此之外,委托模式还有一个缺点:如果类要分别使用多个获取器下载不同数据,那就得在delegate回调方法里根据传入参数来切换。
如果使用块,就可以将实现代码与委托者内联在一起。
在设计API时,如果用到了handler块,那就可以增加一个参数,使调用者可以通过此参数来决定应该把块安排在哪个队列上执行。
用块引用其所属对象时不要出现保留环
使用块很容易导致“保留环”
有两种常见情况。第一种如下例:
当使用block捕获self时,就可能造成这种情况,这时应该等闭包执行完后,再打破保留环。
另一种情况是互相引用,这时常见的方法是不保留引用,设定一套机制,令获取器对象自己设法保持存活。
多用派发队列,少用同步锁
在GCD出现之前,有两种办法来实现同步机制,第一种是“同步块”(@synchronized),第二种是直接使用NSLock对象。这两种方法都有其缺陷,替代方案就是GCD。
有种简单而高效的办法可以代替同步块或锁对象,那就是使用“串行同步队列”。GCD在底层实现。可以做许多优化。
比如属性的存取:
将属性的访问操作都放在串行队列中,就可以实现同步。
如果把设置方法改为异步派发,就可以进一步优化:
然而,获取方法与设置方法不能并发执行,但多个获取方法可以并发执行。将并发队列与栅栏块结合,可以进一步优化。
在队列中,栅栏块必须单独执行,不能与其他块并行。
实现代码也很简单:
_syncQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
- (NSString*)someString {__block NSString *localSomeString;dispatch_sync(_syncQueue, ^{localSomeString = _someString;});return localSomeString;
}
- (void)setSomeString:(NSString*)someString{dispatch_barrier_async(_syncQueue, ^{_someString = someString;});
}
多用GCD,少用performSelector系列方法
使用performSelector方法,可以动态绑定消息,如下图:
但是这种方法不仅可能导致内存泄漏,还很难传达一些非对象类型参数。
避免这些限制和缺陷,方法就是使用块,而perform方法提供的那些线程功能,都可以通过在大中枢派发机制中使用块来执行,延后执行可以用dispatch_after来实现,在另一个线城上执行任务可以通过dispatch_sync及dispatch_async来实现。
掌握GCD及操作队列的使用时机
有时使用NSOperationQueue要比使用GCD技术要更合适。
用NSOperationQueue类的“addOperationWithBlock:”方法搭配NSBlockOperation类使用操作队列,语法与GCD非常类似,但使用下来有以下好处:
通过Dispatch Group机制,根据系统资源状况来执行任务
Dispatch group是GCD的一项特性,能够把任务分组。
与dispatch group相关的有以下几个函数:
dispatch_group_tdispatch_group_create// 创建分组
void dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_bloack_t block);//管理分组
void dispatch_group_enter(dispatch_group_t group);
void dispatch_group_leave(dispatch_group_t group);//管理分组
有两个方法可以用于等待dispatch group执行完毕:
long dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);
void dispatch_group_notify(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block);
二者的区别是:前者会阻塞当前线程,而后者只会在完成任务后进行通知。
未必一定要使用dispatch group,使用异步派发加单个队列也可以实现该效果。然而,使用dispatch group,GCD会根据系统资源状况来调度这些任务。若不采用group,则不仅性能有所下降,还需要额外代码来防止死锁。
使用dispatch_once来执行只需运行一次的线程安全代码
在GCD中,有一种很好的方式实现单例,采用以下函数:
void dispatch_once(dispatch_once_t *token, dispatch_block_t block);
此函数接受一个参数,只要这个参数相同,那么这个块里的代码便只执行一次。
可以这样实现单例:
这个参数应该声明在static或global作用域中。
不要使用dispatch_get_current_queue
dispatch_get_current_queue这个函数已经被弃用了。使用这个函数时,容易造成死锁。并且这个函数的行为也总是与预计不符。因为队列存在一套层级体系。
所以使用该函数检查当前队列是否为执行同步派发所用的队列,并不总是奏效。这个函数所返回的不一定是API指定的那个,有可能是API内部的那个同步队列。
为了解决这个问题,最好的办法是通过GCD提供的功能来设定“队列特有数据”,通过队列特有数据来解决不可重入导致的死锁。
系统框架
熟悉系统框架
许多系统框架可以直接使用,最重要的是Foundation与CoreFoundation。
许多常见任务都能用框架来做,例如音频与视频处理、网络通信、数据管理等。
多用枚举块,少用for循环
遍历collection有四种方式,最基本的是for循环,其次是NSEnumerator类和for...in...快速便利法,最新、最先进的是“块枚举法”。
以数组为例,NSArray中定义了这个方法
- (void)enumerateObjectsUsingBlock:(void(^)id object, NSUInteger idx, BOOL *stop)block
通过这种方法遍历collection,可以直接从块里获取更多信息。遍历数组时可以知道当前下标,遍历字典可以同时获取键值,还可以修改块的方法签名以免进行类型转换操作。
对自定义其内存管理语义的collection使用无缝桥接
使用无缝桥接技术,可以在Foudation框架中的OC对象与CoreFoudation框架中的C语言数据结构之间来回转换。
使用无缝桥接,可以将collection转换为具备特殊内存管理语义的collection。
比如字典的键为“拷贝”,而值为“保留”,这时就只能使用无缝桥接来改变语义。
CF框架中的可变字典叫CFMutableDictionary,可通过下列方法来制定键和值的内存管理语义:
构建缓存时选用NSCache而非NSdictionary
构建缓存时,应选用NSCache而非NSdictionary。
NSCache的优势在于:当系统资源快要耗尽时,它可以自动删减缓存。
NSCache对象可以设置上限来限制缓存中的对象总个数和成本。
NSCache经常与NSData和NSPurgeableData搭配使用。将NSPurgeableData与NSCache搭配使用,可以实现自动清除数据的功能。
精简initiakize与load的实现代码
类的初始化有两个方法,分别是load和initialize
load方法的问题在于,执行时系统处于“脆弱状态”,在执行时必然执行超类的load方法,如果依赖程序库,那库里所有相关类的load方法必定会先执行,但是根据某个库,无法判定各个类的载入顺序。因此,在load方法里使用其他类是不安全的。
load方法务必实现精简一些,因为整个程序在执行load时都会阻塞。
initialize方法会在程序首次调用该类之前调用且只调用一次。它与load不同之处在于:
1.initiakize为惰性调用
2.执行initialize时,系统处于正常状态,也能确保一定是“线程安全的环境”中执行。
3.如果某个类为实现initialize,就会运行超类的实现代码。
initialize方法在实现时也尽量精简。
别忘了NSTimer会保留其目标对象
使用重复执行模式的计时器,很容易引入“保留环”
如果创建本类的实例,并调用startPolling方法,创建计时器时,由于目标对象是self,所以要保留此实例。然而,实例也保留了计时器。因此就产生了保留环。
这时可以拓展NSTimer的功能,用“块”来打破保留环。不过需要创建分类,将实现代码加入分类中。
- (void)startPolling{__weak EOCClass *weakSelf = self;_pollTimer = [NSTimer eoc_scheduledTimerWithTimeInterval:5.0 block: ^{EOCClass *strongSelf = weakSelf;[strongSelf p_doPoll];} repeats:YES];
}
这段代码先定义了一个弱引用,令其指向self,然后捕获这个引用,而不是原本的self变量,这样self就不会被计时器所保留块开始执行时,立即生成strong引用,以保证实例在执行期间持续存活。
相关文章:
《Effective Objective-C》阅读笔记(下)
目录 内存管理 理解引用计数 引用计数工作原理 自动释放池 保留环 以ARC简化引用计数 使用ARC时必须遵循的方法命名规则 变量的内存管理语义 ARC如何清理实例变量 在dealloc方法中只释放引用并解除监听 编写“异常安全代码”时留意内存管理问题 以弱引用避免保留环 …...
深度生成模型(二)——基本概念与数学建模
上一篇笔记中提到了端到端模型底层核心采用了深度生成模型,先简单梳理一下 生成式人工智能(Artificial Intelligence Generated Content,AIGC)经历了从早期基于概率模型和规则系统的方法到现代深度生成模型的跨越式发展 深度神经…...
4.WebSocket 配置与Nginx 的完美结合
序言 在现代 web 应用中,WebSocket 作为一种全双工通信协议,为实时数据传输提供了强大的支持。若要确保 WebSocket 在生产环境中的稳定性和性能,使用 Nginx 作为反向代理服务器是一个明智的选择。本篇文章将带你了解如何在 Nginx 中配置 Web…...
【R语言】dplyr包经典函数summarise函数
dplyr包经典函数summarise函数,后面改名乘reframe函数了,但是summarise仍然适用 这个函数的返回结果是一个新的数据框,下面讲一下几种常见用法 示例数据为R自带的数据集mtcars 1.不分组 mtcars %>%summarise(mean mean(disp), n n()…...
Cuppa CMS v1.0 任意文件读取(CVE-2022-25401)
漏洞简介: Cuppa CMS v1.0 administrator/templates/default/html/windows/right.php文件存在任意文件读取漏洞 漏洞环境: 春秋云镜中的漏洞靶标,CVE编号为CVE-2022-25401 漏洞复现 弱口令行不通 直接访问administrator/templates/defau…...
8.Dashboard的导入导出
分享自己的Dashboard 1. 在Dashboard settings中选择 JSON Model 2. 导入 后续请参考第三篇导入光放Dashboard,相近...
RabbitMQ 的介绍与使用
一. 简介 1> 什么是MQ 消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已。 其主要用途:不同进程Process/线程T…...
unity学习58:下拉列表框 dropdown的caption和options
目录 1 下拉列表框 dropdown 1.1 创建dropdown 1.2 dropdown的子物体构成 1.3 drop的子物体构成:默认灰色的模板 template 1.3.1 默认灰色的模板 template 实际是生效的,只是不直接显示 1.3.2 其中 item下面是下拉选项的格式 1.3.3 可以修改和新增 1.4 drop…...
STM32中使用PWM对舵机控制
目录 1、硬件JIE 2、PWM口配置 3、角度转换 4、main函数中应用 5、工程下载连接 1、硬件介绍 单片机:STM32F1 舵机:MG995 2、PWM口配置 20毫秒的PWM脉冲占空比,对舵机控制效果较好 计算的公式: PSC、ARR值的选取…...
如何免费使用稳定的deepseek
0、背景: 在AI辅助工作中,除了使用cursor做编程外,使用deepseek R1进行问题分析、数据分析、代码分析效果非常好。现在我经常会去拿行业信息、遇到的问题等去咨询R1,也给了自己不少启示。但是由于官网稳定性很差,很多…...
STM32内存五区及堆栈空间大小设置(启动文件浅析)
前言 嘿,朋友们!今天咱们来聊聊STM32的内存五区和堆栈空间大小设置。这可是嵌入式开发里的“必修课”,要是没整明白,程序说不定就“翻车”了。别担心,我这就带你一步步搞懂这事儿,让你轻松上手,…...
LVS+Keepalived高可用群集配置案例
以下是一个 LVSKeepalived 高可用群集配置案例: 1、环境准备 LVS 主调度器(lvs1):IP 地址为 192.168.8.101,心跳 IP 为 192.168.4.101LVS 备调度器(lvs2):IP 地址为 192.168.8.102…...
MySQL 中如何解决深度分页的问题? MySQL中 join、inner join、left join、right join区别
MySQL 中如何解决深度分页的问题? 在 MySQL 中解决深度分页问题的核心思路是减少扫描的数据量,尤其是避免通过 LIMIT offset, size 导致的大范围数据扫描。以下是三种优化方法及其原理、适用场景和注意事项: 1. 子查询 覆盖索引(…...
本地部署DeepSeek-R1(Ollama+Docker+OpenWebUI知识库)
安装Ollama 打开 Ollama官网 https://ollama.com/下载安装 Ollama服务默认只允许本机访问,修改允许其它主机访问 OLLAMA_HOST0.0.0.0 ollama serve也可以添加系统环境变量 都知道模型体积很大,顺便也通过环境变量修改模型存放位置,我这…...
ubuntu22.04安装docker engine
在Ubuntu 22.04上安装Docker Engine可以通过以下步骤完成: 更新系统包索引: sudo apt update安装必要的依赖包: 这些包允许apt通过HTTPS使用仓库。 sudo apt install -y apt-transport-https ca-certificates curl software-properties-commo…...
Protobuf原理与序列化
本文目录 1. Protobuf介绍2. Protobuf的优势3. 编写Protobuf头部全局定义消息结构具体定义字段类型定义标签号Base128编码 4. TLVProtobuf的TLV编码如何通过Varint表示300? 5. 编译Protobuf6. 构造消息对象 前言:之前写项目的时候只是简单用了下Protobuf…...
Redis|事务
文章目录 是什么能干嘛Redis 事务 VS 数据库事务怎么玩小总结 是什么 首先回想一下什么是数据库的事务?数据库事务是指作为单个逻辑单元执行的一系列操作,具备以下四个关键特性(ACID): 原子性(Atomicity&am…...
树莓百度百科更新!宜宾园区业务再添新篇
树莓集团宜宾园区业务不断拓展,主要体现在以下几个方面: 产业布局 -聚焦数字经济核心领域:涵盖软件开发、人工智能、大数据等,吸引众多上下游企业入驻,形成从芯片研发、软件开发到系统集成的完整产业链条。 -推进“双…...
设计模式教程:模板方法模式(Template Method Pattern)
一、概述 模板方法模式(Template Method Pattern) 是一种行为型设计模式,旨在定义一个操作中的算法骨架,而将一些步骤的具体实现延迟到子类中。通过模板方法模式,父类可以不改变算法结构的情况下,让子类重…...
unity学习54:图片+精灵+遮罩mask,旧版文本 text 和新的TMP文本
目录 1 图片 image 1.1 如果直接导入image 1.2 图片 image 和精灵 sprite 1.2.1 继续修改上面的格式 texture type 是default 1.2.2 再次关联到UI的 image 物体上就可以了 1.3 图片和遮罩 mask 1.3.1 创建1个父物体和1个子物体,分别都是image 1.3.2 如果父…...
【Java项目】基于Spring Boot的校园闲置物品交易网站
【Java项目】基于Spring Boot的校园闲置物品交易网站 技术简介:采用Java技术、Spring Boot框架、MySQL数据库等实现。 系统简介:校园闲置物品交易网站是一个典型的管理系统,主要功能包括管理员:首页、个人中心、用户管理、商品类…...
网页制作08-html,css,javascript初认识のhtml使用框架结构,请先建立站点!
框架一般由框架集和框架组成。 框架集就像一个大的容器,包括所有的框架,是框架的集合。 框架是框架集中一个独立的区域用于显示一个独立的网页文档。 框架集是文件html,它定义一组框架的布局和属性,包括框架的数目,框架…...
DeepSeek-R1:通过强化学习激励大语言模型的推理能力
摘要 本文介绍了我们的第一代推理模型,DeepSeek-R1-Zero 和 DeepSeek-R1。DeepSeek-R1-Zero 是通过大规 模强化学习(RL)训练的模型,在没有使用监督微调(SFT)这个前置步骤的情况下,展示了卓越的推…...
hbase笔记总结1
hbase是nosql的一种,非关系型数据库,not only sql,可处理大规模、高并发的数据,是web2.0以后的产物hbase的扩展性和灵活性更好,而且筛选能力相较于MySQL更优nosql的四大特点: 灵活的数据模型 (1…...
关于C++中static_cast、const_cast、dynamic_cast的简单介绍
在C中,static_cast、const_cast 和 dynamic_cast 是用于类型转换的关键字,它们的行为和适用场景有显著区别。以下是它们的核心差异和用法总结: 1. static_cast 用途 用于明确且安全的类型转换,通常用于编译时已知类型关系的场景…...
计算机毕业设计 ——jspssm513Springboot 的小区物业管理系统
作者:程序媛9688 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等。 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,还有大家在毕设选题(免费咨询指导选题)…...
详解Tomcat下载安装以及IDEA配置Tomcat(2023最新)
目录 步骤一:首先确认自己是否已经安装JDK步骤二:下载安装Tomcat步骤三:Tomcat配置环境变量步骤四:验证Tomcat配置是否成功步骤五:为IDEA配置Tomcat 步骤一:首先确认自己是否已经安装JDK jdk各版本通用安…...
端口映射/内网穿透方式及问题解决:warning: remote port forwarding failed for listen port
文章目录 需求:A机器是内网机器,B机器是公网服务器,想要从公网,访问A机器的端口方式:端口映射,内网穿透,使用ssh打洞端口:遇到问题:命令执行成功,但是端口转发…...
2024年第十五届蓝桥杯大赛软件赛省赛Python大学A组真题解析
文章目录 试题A: 拼正方形(本题总分:5 分)解析答案试题B: 召唤数学精灵(本题总分:5 分)解析答案试题C: 数字诗意解析答案试题A: 拼正方形(本题总分:5 分) 【问题描述】 小蓝正在玩拼图游戏,他有7385137888721 个2 2 的方块和10470245 个1 1 的方块,他需要从中挑出一些…...
win11编译pytorch cuda128版本流程
Geforce 50xx系显卡最低支持cuda128,torch cu128 release版本目前还没有释放,所以自己基于2.6.0源码自己编译wheel包。 1. 前置条件 1. 使用visual studio installer 安装visual studio 2022,工作负荷选择【使用c的桌面开发】,安装完成后将…...
AI人工智能机器学习之降维和数据压缩
1、概要 本篇学习AI人工智能机器学习之降维和数据压缩,以主成分分析(PCA, Principal Component Analysis)为例,从代码层面讲述机器学习中的降维和数据压缩。 2、降维和数据压缩 - 简介 在机器学习和数据分析中,降维&…...
EasyExcel 使用指南:基础操作与常见问题
文章目录 1. EasyExcel 简介2. 基础操作2.1. 写入 Excel 🔥2.2. 读取 Excel ✅2.3. 使用模板 🎨 3. 常见问题与解决方案3.1. 处理日期格式 📅3.2. 数据写入失败:占位符无法匹配 ❌3.3. 内存溢出:大数据量处理 ⚡3.4. 空…...
本地搭建Koodo Reader书库结合内网穿透打造属于自己的移动图书馆
文章目录 前言1. Koodo Reader 功能特点1.1 开源免费1.2 支持众多格式1.3 多平台兼容1.4 多端数据备份同步1.5 多功能阅读体验1.6 界面简洁直观 2. Koodo Reader安装流程2.1 安装Git2.2 安装Node.js2.3 下载koodo reader 3. 安装Cpolar内网穿透3.1 配置公网地址3.2 配置固定公网…...
Mybatis是如何进行分页的?与Mybatis-plus的区别在哪里?
MyBatis 的分页方式及其与 MyBatis-Plus 的区别可以总结如下: MyBatis 的分页实现 逻辑分页(内存分页) 使用 RowBounds 对象,在查询时传入参数,MyBatis 会在结果集返回后,在内存中手动截取指定范围的数据。…...
MySQL 主从同步配置及操作步骤
主从同步是一种常见的数据复制技术,它通过将主库的数据同步到一个或多个从数据库中来保证数据的一致性。从库通过读取主库的 binlog 文件来获取更新并进行同步。 主从复制的方式有三种: 异步复制:不需要从库确认,主库提交数据后…...
【软考-架构】备战2025软考
新老教材对比 科目1(信息系统综合)考点详解 科目2(系统架构设计案例)考点详解 科目3(系统架构设计论文)考点详解 趋于越来越具体 学习方法推荐 第一阶段 – 基础知识阶段 建议一个半月; 先过…...
基于Spark的电商供应链系统的设计与实现
目录 1.研究背景与意义 2、国内外研究现状 3、相关理论与技术 (一)分布式计算系统Spark (二)数据仓库Hive (三)读取服务器本地磁盘的日志数据Flume (四)分布式消息队列Kafka …...
DaoCloud 亮相 2025 GDC丨开源赋能 AI 更多可能
2025 年 2 月 21 日至 23 日,上海徐汇西岸,2025 全球开发者先锋大会以 “模塑全球,无限可能” 的主题,围绕云计算、机器人、元宇宙等多元领域,探讨前沿技术创新、应用场景拓展和产业生态赋能,各类专业论坛、…...
基于coze+微信小程序实现图片上传并利用大模型解析
项目截图: 实现代码(直接搬去可用) 前提:需要填写你的oss配置coze的api授权配置!!! <template><view class"container"><!-- 高斯模糊背景 --><view class&qu…...
CSS 对齐:深入理解与技巧实践
CSS 对齐:深入理解与技巧实践 引言 在网页设计中,元素的对齐是至关重要的。一个页面中元素的对齐方式直接影响到页面的美观度和用户体验。CSS 提供了丰富的对齐属性,使得开发者可以轻松实现各种对齐效果。本文将深入探讨 CSS 对齐的原理、方法和技巧,帮助开发者更好地掌握…...
Dify部署
Dify部署 安装docker 要在CentOS 7上部署Docker社区版,您可以按照以下步骤进行操作: 卸载旧版本的Docker(如果有): yum remove docker docker-client docker-client-latest docker-common docker-latest docker-l…...
MyBatis-Plus 对比传统 MyBatis 的优势
在现代的 Java 开发中,MyBatis 和 MyBatis-Plus 都是流行的持久层框架。MyBatis 是一个轻量级的 ORM 框架,帮助开发者通过映射文件或注解方式来执行 SQL 操作。MyBatis-Plus 是在 MyBatis 基础上进行的增强,提供了许多简化和优化功能…...
被AWS反撸了,试一下能否申请退还
经过来回几轮沟通,已扣的42美金将退回31美金,未扣的16美金将免除扣款。 31美金的具体计算方法我不知道,对方的回复如下(是了,AWS的客服是用中文回复的): 我理解此结果可能不完全符合您所期望的…...
基于Spring Boot的产业园区智慧公寓管理系统设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
MySQL 事务笔记
MySQL 事务笔记 目录 事务简介事务操作事务四大特性并发事务问题事务隔离级别总结 事务简介 事务(Transaction)是数据库操作的逻辑单元,由一组不可分割的SQL操作组成。主要用于保证: 多个操作的原子性(要么全部成功…...
SpringBoot 使用 spring.profiles.active 来区分不同环境配置
很多时候,我们项目在开发环境和生产环境的配置是不一样的,例如,数据库配置,在开发的时候,我们一般用测试数据库,而在生产环境,我们要用生产数据库,这时候,我们可以利用 p…...
# C# 中堆(Heap)与栈(Stack)的区别
在 C# 中,堆和栈是两种不同的内存分配机制,它们在存储位置、生命周期、性能和用途上存在显著差异。理解堆和栈的区别对于优化代码性能和内存管理至关重要。 1. 栈(Stack) 1.1 定义 栈是一种后进先出(LIFO࿰…...
IP---网络类型
这只是IP的其中一块内容-网络类型,IP还有更多内容可以查看IP专栏,前一章内容为访问服务器流程,可通过以下路径查看IP----访问服务器流程-CSDN博客,欢迎指正 2.网络类型 网络类型---根据二层(数据链路层)所…...
jQuery UI API 文档
jQuery UI API 文档 引言 jQuery UI 是一个基于 jQuery 的用户界面库,它提供了丰富的交互式组件和效果,使得网页开发变得更加简单和高效。本文档旨在为开发者提供全面的 jQuery UI API 信息,帮助您更好地理解和应用 jQuery UI。 jQuery UI 简介 什么是 jQuery UI? jQu…...
rust 前端npm依赖工具rsup升级日志
rsup是使用 rust 编写的一个前端 npm 依赖包管理工具,可以获取到项目中依赖包的最新版本信息,并通过 web 服务的形式提供查看、升级操作等一一系列操作。 在前一篇文章中,记录初始的功能设计,自己的想法实现过程。在自己的使用过…...