【iOS】单例、通知、代理
1 单例模式
1.1 什么是单例
单例模式在整个工程中,相当于一个全局变量,就是不论在哪里需要用到这个类的实例变量,都可以通过单例方法来取得,而且一旦你创建了一个单例类,不论你在多少个界面中初始化调用了这个单例方法取得对象,它们所有的对象都是指向的同一块内存的存储空间(即单例类保证了该类的实例对象是唯一存在的一个)。
1.2 单例模式的优缺点
-
优点
- 一个类只被实例化一次,提供了对唯一实例的受控访问。
- 节省系统资源。
- 允许可变数目的实例。
-
缺点
- 一个类只有一个对象,可能造成责任过重,在一定程度上违背了“单一职责原则”。
- 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
- 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
1.3 单例的实现
单例的实现分为两种:懒汉式和饿汉式。
- 懒汉式:顾名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化。
- 饿汉式:饿了肯定会饥不择食,所以在单例类加载的时候就进行实例化。
特点和选择:
- 由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能,这是以空间换时间。
- 在访问量较小时,采用懒汉实现,这是以时间换空间。
1.3.1 懒汉式
- 使用
@synchronized
static id manager = nil;
+ (instancetype)shareInstance {// 防止多次加锁if (!manager) {@synchronized (self) {if (!manager) {manager = [[super allocWithZone:NULL] init];}}}return manager;
}
第一次if(!manager)判断是为了避免在对象创建后多次访问导致的多次加锁,浪费性能。第二次if(!manager)判断就是判断此时单例是否存在,不存在就重新创建。
- 使用GCD
+ (instancetype)shareInstance {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{manager = [[super allocWithZone:NULL] init];});return manager;
}
dispatch_once它没有使用重量级的同步机制,性能也优于前者,并且更加高效。
dispatch_once
无论使用多线程还是单线程,都只执行一次,在安全的前提下也保证了性能。
dispatch_once
主要是根据onceToken
的值来决定怎么执行代码:
- 当
onceToken
为0时,线程执行dispatch_once
的block
中的代码。 - 当
onceToken
为-1时,线程跳过dispatch_once
的block
中的代码。 - 当
onceToken
为其他值时,线程被阻塞,等待onceToken
值改变。
dispatch_once
的执行流程:
- 当线程调用
shareInstance
,此时onceToken
为0,执行dispatch_once
的block
中的代码,此时onceToken
中的值为其他值。 - 这时如果有其他线程再调用
shareInstance
方法时,onceToken
值为其他值,线程阻塞。 - 当
block
线程执行完block
后,onceToken
变为-1。其他线程不再阻塞,跳过block
。 - 下次再调用
shareInstance
时,onceToken
为-1,直接跳过block
。
1.3.2 饿汉式
当类被加载的时候就创建,因为一个类在整个生命周期中只会被加载一次,所以它肯定只有一个线程对其进行访问,此时再创建他就是线程安全的,就不需要使用线程锁来保证其不会被多次创建。
static id manager = nil;+ (void)load {[super load];manager = [[super allocWithZone:NULL] init];
}+ (instancetype)shareInstance {return manager;
}- (instancetype)copyWithZone:(NSZone *)zone {return manager;
}- (instancetype)mutableCopyWithZone:(NSZone *)zone {return manager;
}+ (instancetype)allocWithZone:(struct _NSZone *)zone {return manager;
}
1.4 关于复写
根据单例的定义,我们只能允许存在一个该单例对象,所以我们要扼制其创建出新的该单例类的对象,保证对象的唯一性。所以我们要复写一些可以自己创建对象的方法例如copy
、mutableCopy
。为了彻底保证用户无法创建新的该单例类的对象,我们一般会重写到XXXWithZone:
方法。
- (instancetype)copyWithZone:(NSZone *)zone {return manager;
}- (instancetype)mutableCopyWithZone:(NSZone *)zone {return manager;
}+ (instancetype)allocWithZone:(struct _NSZone *)zone {return manager;
}
2 通知
2.1 几个点
- 观察者和被观察者都无需知晓对方,只需要通过标记在
NSNotificationCenter
中找到监听该通知所对应的类,从而调用该类的方法。 - 并且在
NSNotificationCenter
中,观察者可以只订阅某一特定的通知,并对齐做出相应操作,而不用对某一个类发的所有通知都进行更新操作。 NSNotificationCenter
对观察者的调用不是随机的,而是遵循注册顺序一一执行的,并且在该线程内是同步的。
2.2 通知使用步骤
总体分为三步走:
- 在要传递参数的地方,发送通知给通知中心:
[[NSNotificationCenter defaultCenter] postNotificationName:@"temp" object:nil userInfo:@{@"content": self.myTextField.text}];
- 在接收参数的地方注册通知,并实现定义方法
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(Notificate:) name:@"temp" object:nil];
- 在不需要通知的时候,移除通知
[[NSNotificationCenter defaultCenter] removeObserver:self];
2.3 一些问题
2.3.1 通知的发送时同步的,还是异步的?发送消息与接收消息的线程是同一个线程么?
通知中心发送通知给观察者是同步的,也可以用通知队列(NSNotificationQueue
)异步发送通知。
在抛出通知以后,观察者在通知事件处理完成以后(可以通过休眠3秒来测试),抛出者才会往下继续执行,也就是说这个过程默认是同步的;当发送通知时,通知中心会一直等待所有的 observer
都收到并且处理了通知才会返回到 poster
。
接收通知的线程,和发送通知所处的线程是同一个线程。也就是说如果要在接收通知的时候更新 UI,需要注意发送通知的线程是否为主线程。
- (void)viewDidLoad {[super viewDidLoad];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"NotificationName" object:nil];
}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);dispatch_async(queue, ^{NSLog(@"--currect thread:%@", [NSThread currentThread]);NSLog(@"Begin post notification");[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:nil];NSLog(@"End");});
}- (void)test {NSLog(@"--current thread:%@", [NSThread currentThread]);NSLog(@"Handle notification and sleep 3s");sleep(3);
}
2.3.2 如何使用异步发送通知?
- 让通知事件处理方法在子线程中执行。
- (void)viewDidLoad {[super viewDidLoad];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"NotificationName" object:nil];
}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {NSLog(@"--currect thread:%@", [NSThread currentThread]);NSLog(@"Begin post notification");[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:nil];NSLog(@"End");
}- (void)test {dispatch_queue_t queue = dispatch_queue_create("test.queue", DISPATCH_QUEUE_SERIAL);dispatch_async(queue, ^{NSLog(@"--currect thread:%@", [NSThread currentThread]);NSLog(@"Handle notification and sleep 3s");sleep(3);NSLog(@"Test End");});
}
- 可以通过
NSNotificationQueue
的enqueueNotification: postingStyle:
和enqueueNotification: postingStyle: coalesceMask: forModes:
方法将通告放入队列,实现异步发送,在把通告放入队列之后,这些方法会立即将控制权返回给调用对象。
- (void)viewDidLoad {[super viewDidLoad];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(test) name:@"NotificationName" object:nil];
}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {NSLog(@"--current thread:%@", [NSThread currentThread]);NSLog(@"Begin post notification");NSNotification *notification = [NSNotification notificationWithName:@"NotificationName" object:nil];[[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];NSLog(@"End");
}- (void)test {NSLog(@"--current thread:%@", [NSThread currentThread]);NSLog(@"Handle notification and sleep 3s");sleep(3);NSLog(@"Test End");
}
2.3.3 NSNotificationQueue 和 runloop 的关系?
postringStyle
参数就是定义通知调用和 runloop
状态之间关系。
该参数的三个可选参数:
1.NSPostWhenIdle
:通知回调方法是等待到当下线程 runloop
进入等待状态才会调用。
2.NSPostASAP
:通知回调方法是等待到当下线程 runloop
开始接收事件源的时候就会调用。
3.NSPostNow
:其实和直接用默认的通知中心添加通知是一样的,通知马上调用回调方法。
2.3.3 页面销毁时不移除通知会崩溃吗?
在观察者对象释放之前,需要调用 removeOberver
方法将观察者从通知中心移除,否则程序可能会出现崩溃。但从 iOS9 开始,即使不移除观察者对象,程序也不会出现异常。
这是因为在 iOS9 以后,通知中心持有的观察者由 unsafe_unretained
引用变为weak
引用。即使不对观察者手动移除,持有的观察者的引用也会在观察者被回收后自动置空。但是通过 addObserverForName:object: queue:usingBlock:
方法注册的观察者需要手动释放,因为通知中心持有的是它们的强引用。
2.3.4 多次添加同一个通知会是什么结果?多次移除通知呢?
- 多次添加同一个通知,观察者方法会调用多次
- 多次移除,没关系。
2.3.5 为什么注册通知时可以空名注册,但是发送通知时却不可以?
- 当注册通知时,空的通知名称表示监听所有的通知。这在某些情况下是非常有用的,特别是当你希望监听某个对象发送的所有通知时,而不仅限于特定的通知名称。
- 发送通知时不可以使用空的通知名称,这是因为发送通知时需要指定一个具体的通知名称,以便通知中心能够将通知正确地发送给对应的观察者。如果在发送通知时使用空的通知名称,通知中心将无法确定通知应该发送给哪些观察者,这样会导致通知无法被正确处理。
2.3.6 object是干嘛的?是不是可以用来传值?
在观察者的添加中,object
参数指定了通知的发送者,只有当通知的发送者与观察者添加时指定的 object
参数相同,才会接收到通知。如果观察者添加时指定了具体的 object
对象,那么在发送通知时,通知的 object
参数必须与观察者添加时的 object
参数相匹配,否则观察者将不会接收到通知。如果需要传值请用userInfo
,而不是object
。
示例,以下方法就不会接收到通知:
// 添加观察
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"TestNotification" object:@1];
// 通知发送
[NSNotificationCenter.defaultCenter postNotificationName:@"TestNotification" object:nil];
这是因为在添加观察者时,指定了 object
参数为 @1
,即一个 NSNumber
类型的对象。而在发送通知时,指定的 object
参数为 nil
。
3 代理
3.1 代理的使用步骤
- 在B视图控制器声明一份协议
@protocol MyViewControllerDelegate <NSObject>- (void)changUILabelText:(NSString *)string;@end
- 在B视图控制器中声明一个代理属性
@property (nonatomic, weak) id<MyViewControllerDelegate> delegate;
- 在B视图控制器中想要回传值的地方写代理执行的方法
[self.delegate changeUILabelText:self.myTextField.text];
- 在A视图控制器里签订代理协议
@interface ViewController : UIViewController <MyViewControllerDelegate>@property (nonatomic, strong) MyViewController *myView;@end
- A中签订代理人
self.myView = [[MyViewController alloc] init];self.myView.delegate = self;
- 实现协议方法
- (void)changUILabelText:(NSString *)string {NSLog(@"%@", string);
}
3.2 代理的循环引用
代理的循环引用是指在代理模式中,由于相互强引用,导致两个对象(通常是委托方和代理方)之间形成了一个循环引用的关系,从而导致内存泄漏问题。由于这种循环引用,当委托方和代理方相互强引用对方时,它们的引用计数无法降为0,导致它们所占用的内存无法被正确释放,从而造成内存泄漏。
为了避免代理的循环引用,可以采用以下几种方法之一:
- 使用弱引用(weak reference):在委托方的属性声明中,将代理方的引用设为弱引用,这样就不会形成循环引用。例如:@property (nonatomic, weak) id delegate;。但需要确保代理方在使用期间不会被提前释放。
- 使用代理方的生命周期控制:在委托方中持有代理方的引用时,可以根据具体情况,在适当的时候解除对代理方的引用,避免循环引用。
- 使用 block 或通知来替代代理模式:在某些情况下,可以使用 block 或通知来替代代理模式,避免循环引用的问题。
选择合适的方法取决于具体的业务逻辑和需求,确保代理模式的使用不会造成循环引用和内存泄漏。
4. KVO\KVC\单例模式\通知\代理\Block
4.1 代理和通知的区别
- 效率:代理比通知高;
- 关联:代理是强关联,委托和代理双方互相知道。通知是弱关联,不需要知道是谁发,也不需要知道是谁接收;
- 代理是一对一的关系,通知是一对多的关系;代理要实现对多个类发出消息可以通过将代理者添加入集合类后遍历,或通过消息转发来实现。
- 代理一般行为需要别人来完成,通知是全局通知;
4.2 KVO和通知的区别
- 相同:都是一对多的关系;
- 不同:通知是需要被观察者先主动发出通知,观察者注册监听再响应,比KVO多了发送通知这一步;
- 监听范围:KVO是监听一个值的变化,通知不局限于监听属性的变化,还可以对多种多样的状态变化进行监听,通知的监听范围广,使用更灵活;
- 使用场景:KVO的一般使用场景是监听数据变化,通知是全局通知;
4.3 block和代理的区别
- 相同点:block和代理都是回调的方式。使用场景相同。
- 不同点:
- block集中代码块,而代理分散代码块,所以 block 更适用于轻便、简单的回调,如网络传输,代理适用于公共接口较多的情况,这样做也更易于解耦代码架构;
- block运行成本高,block出栈时,需要将使用的数据从栈内存拷贝到堆内存。当然如果是对象就是加计数,使用完或block置为 nil 后才消除,而代理只是保存了一个对象指针,直接回调,并没有额外消耗,相对C的函数指针,只是多做了一个查表动作;
总结表:
方法 | delegate | NSNotification | KVO | block |
---|---|---|---|---|
优点 | 1.逻辑清楚2代码可读性较强3.编译器会检查是否实现了所有方法4.-个controller可以有多个协议5.减少代码耦合性 | 1.代码量小2.可以实现一对多3.传值方便快捷 | 1.可以简单的实现两个对象同步2.可以观察当前值和先前值3.能够对非我们创建的对象,即内部对象的状态改变作出响应,而且不需要改变内部对象(SDK对象)的实现 | 1.逻辑清晰2.同一函数需要低啊用多次的时候,节省代码量3.block可以存储在属性里4.增强代码可读性5.配合GCD优秀的解决多线程 |
缺点 | 1.定义需要的代码多2.释放时需要将delegate置为nil,否则调用释放的delegate会crash3.一个controller有多个同一协议的deleqate.难以区分4.跨层传值监听,会使程序层次混乱5.容易引起循环引用 | 1.编译器不会发现是否可以正确处理2.释放注册对象时,需要取消注册,否则可能会crash3.逻辑不清晰 | 1.观察的属性使用“string”,编译器不会出现警告和检查(编译器无法在编译时捕获拼写错误或其他错误类型)2.属性重构后需要再次修改(属性名称变更、属性类型变更、属性移除或新增) | 1.可能引起循环引用2.block中的代码会自动retain.容易造成内存泄漏 |
建议使用场景 | controller与其他任何对象通信,回调方法中一对多的情况、UI响应事件 | 代码上需要处理的东西很简单,两个毫无关联的对象之间通信 | 需要监视一个属性 | 回调方法,简单值的传递 |
5 设计模式总结
- KVO/通知 -------> 观察者模式
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
优势:解耦合
接口隔离原则、开放-封闭原则
- KVC --------> KVC模式
KVC 提供了一种更加灵活和强大的属性访问方式,使得开发者能够以简单的方式操作对象的属性和集合,减少了许多重复的代码和复杂性。它是 Cocoa 框架中的一个重要特性,为开发者带来了便利和高效性。但需要注意的是,使用 KVC 时需要保证对象的属性符合 KVC 规范,即属性通过一定的命名规则对应到键,这样才能正确地使用 KVC 进行属性访问和操作。
- 单例模式
利用应用程序只有一个该类的实例对象这一特殊性来实现资源共享。
优势:使用简单,延时求值,易于跨模块
劣势:这块内存知道程序退出时才能释放
单一职责原则
- 代理模式
委托方将不想完成的任务交给代理方处理,并且需要委托方通知代理方才能处理。
优势: 解耦合
开放-封闭原则
举例:tableview的数据源和代理
- 策略模式
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
优势:使算法的变化独立于使用算法的用户
接口隔离原则、多用组合,少用继承、针对接口编程,而非实现
举例:账号密码输入格式的判断、NSArray的sortedArrayUsingSelector等等
- MVC模式
将程序书写分为三层,分别为模型、视图、控制器,每层都有各自的职责完成各自的工作。
优势: MVC模式使系统,层次清晰,职责分明,易于维护
对扩展开放-对修改封闭
- MVVM模式
用于解决MVC模式下C层代码冗杂的情况(过多的网络请求以及业务逻辑处理)而出现的MVVM模式,其相比于MVC多了一层ViweModel(业务处理和数据转化)层,专门用于处理数据。
当功能简单时,MVVM反而会增加很多代码,所以对于简单的功能,MVC更加的方便。
- 三种工厂模式
通过给定参数来返回对应的实例,完全对用户隐藏其实现的原理。
优势:易于替换,面向抽象编程
依赖倒置原则
设计模式:MVC模式、单例模式、观察者模式、MVVM模式、工厂模式、代理模式、策略模式
适配器模式、模板模式、外观模式、创建模式
想要深入了解可以看看这个:iOS 设计模式
相关文章:

【iOS】单例、通知、代理
1 单例模式 1.1 什么是单例 单例模式在整个工程中,相当于一个全局变量,就是不论在哪里需要用到这个类的实例变量,都可以通过单例方法来取得,而且一旦你创建了一个单例类,不论你在多少个界面中初始化调用了这个单例方…...

从Vue2到Vue3【五】——新的组件(Fragment、Teleport、Suspense)
系列文章目录 内容链接从Vue2到Vue3【零】Vue3简介从Vue2到Vue3【一】Composition API(第一章)从Vue2到Vue3【二】Composition API(第二章)从Vue2到Vue3【三】Composition API(第三章)从Vue2到Vue3【四】C…...

PostgreSQL——sql文件导入
Windows方式: 进入PostgreSQL安装目录的bin,进入cmd 执行命令: psql -d 数据库名 -h localhost -p 5432 -U 用户名 -f 文件目录 SQL Shell: 执行命令: \i 文件目录(Windows下要加引号和双斜线)...
[SQL挖掘机] - 全连接: full join
介绍: 在sql中,join是将多个表中的数据按照一定条件进行关联的操作。全连接(full join)是一种连接类型,它会返回所有满足连接条件的行,同时还包括那些在左表和右表中没有匹配行的数据。 在进行全连接时,会…...
SpringDataJpa 实体类—主键生成策略
主键配置 IdGeneratedValue(strategy GenerationType.IDENTITY)Column(name "cust_id")private Long custId;//主键 Id:表示这个注解表示此属性对应数据表中的主键GeneratedValue(strategy GenerationType.IDENTITY) 此注解表示配置主键的生成策…...
【LeetCode 算法】Parallel Courses III 并行课程 III-拓扑
文章目录 Parallel Courses III 并行课程 III问题描述:分析代码拓扑 Tag Parallel Courses III 并行课程 III 问题描述: 给你一个整数 n ,表示有 n 节课,课程编号从 1 到 n 。同时给你一个二维整数数组 relations ,其…...
进行消息撤回功能的测试时,需要考虑哪些?
进行消息撤回功能的测试时,可以考虑以下测试点: 1. 功能可用性测试:确认消息撤回功能是否能够正常使用,并且在不同的场景下(例如单聊、群聊)是否表现一致。 2. 撤回时限测试:检查消息撤回的时…...

C语言动态内存管理(三)
目录 五、C/C程序的内存开辟1.图解2.关键点 六、柔性数组1.什么是柔性数组2.两种语法形式3.柔性数组的特点4.柔性数组的创建及使用在这个方案中柔性数组的柔性怎么体现出来的? 5.不用柔性数组,实现数组可大可小的思路6.对比 总结 五、C/C程序的内存开辟 1.图解 &a…...

通过cmake工程生成visual studio解决方案
1、前言 visual studio是一个很强大的开发工具,这个工具主要是通过解决方案对我们的源码进行编译等操作。但是我们很多时候拿到的可能并不是一个直接的解决方案,可能是是一个cmake工程,那么这个时候我们就需要通过cmake工程生成解决方案&…...

STM32CubeMX配置STM32G031多通道ADC + DMA采集(HAL库开发)
时钟配置HSI主频配置64M 勾选打开8个通道的ADC 使能连续转换模式 添加DMA DMA模式选择循环模式 使能DMA连续请求 采样时间配置160.5 转换次数为8 配置好8次转换的顺序 配置好串口,选择异步模式配置好需要的开发环境并获取代码 修改main.c 串口重定向 #include &…...

Vue入门项目——WebApi
Vue入门——WebApi vue3项目搭建组合式API响应式APIreactive()ref() 生命周期钩子computed计算属性函数watch监听函数父子通信模板引用组合选项 vue3项目搭建 简单看下Vue3的优势吧 下载安装npm及node.js16.0以上版本(确保安装成功可用如下代码检查版本࿰…...

【电源专题】电量计参数RSOC/RM/FCC定义
在文章【电源芯片】电量计(Gauge)介绍中我们讲到电量计的功能就是监测电池、计量电量。 那么电量计其实也是有很多算法的,比如【电源专题】电量计估计电池荷电状态方法(开路电压法及库仑计法)的差别文章所说的开路电压法和库仑计法。当然还有如阻抗跟踪法、CEDV算法等。 …...
实际开发中,React应用常见问题【持续更新中】
实际开发中,React应用常见问题【持续更新中】 实际开发中,React应用常见问题【持续更新中】 一、路由相关 “react-router-dom”: “^6.14.2”, “react”: “^18.2.0”, 1、监听路由 import { useLocation } from react-router-domexport default func…...

HTML5前端开发工程师的岗位职责说明(合集)
HTML5前端开发工程师的岗位职责说明1 职责 1、根据产品设计文档和视觉文件,利用HTML5相关技术开发移动平台的web前端页面; 2、基于HTML5.0标准进行页面制作,编写可复用的用户界面组件; 3、持续的优化前端体验和页面响应速度,并保证兼容性和…...
Go编写服务监管程序
前言 程序的目的:一个基于Linux系统下的进程监控与管理工具,它能够监控指定的进程或服务的运行情况,并在发现它们不存在或出现异常时自动进行重启操作。这个程序就像一个可靠的看门狗,时刻守护着系统的稳定运行。 程序的本身是周期…...
API商品详情:详尽呈现产品信息的利器
API商品详情:详尽呈现产品信息的利器 随着电子商务的迅速发展,越来越多的企业和开发者开始关注和利用API来实现灵活、高效的商品展示和推广。而在这一领域中,API商品详情成为了无可替代的利器,为用户提供了极为详尽的产品信息。 …...

Cisco 路由器配置管理
大多数网络中断的最常见原因是错误的配置更改。对网络设备配置的每一次更改都伴随着造成网络中断、安全问题甚至性能下降的风险。计划外更改使网络容易受到意外中断的影响。 Network Configuration Manager 网络更改和配置管理 (NCCM)解决方案ÿ…...
java面试真题附参考答案【下册】
tips:下面简述题为java面试真题,阅读本文且感兴趣的,还有将要面试的小伙伴有条件的准备一下笔和纸,将之转述出来成为自己的知识,希望接下来的面试好运连连 上一册:java面试真题【上册】_CsDn.FF的博客-CSD…...

2023牛客多校第三场 B.Auspiciousness
传送门 前题提要:没得说,赛时根本没想到dp,赛后翻各大题解看了很久,终于懂了dp的做法,故准备写一篇题解. 首先,先定义一下我们的 d p dp dp方程,考虑将处于 [ 1 , n ] [1,n] [1,n]的数当做小数,将处于 [ n 1 , 2 ∗ n ] [n1,2*n] [n1,2∗n]的数当做大数.那么对于我们的摸牌结…...
Numpy—数组的分隔与转置
⛳数组的切分 split 分隔 numpy.split 函数沿特定 的轴将数组分割为子数组,格式如下: numpy.split(ary, indices_or_sections, axis)参数说明: arry:被分割的数组。indices_or_sections:如果是一个整数,就…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...