做为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个个人iOS交流群:638302184,无论你是小白仍是大牛欢迎入驻 ,分享BAT,阿里面试题、面试经验,讨论技术, 与2800+iOS开发者一块儿交流学习成长!
NSString * str1 = @"copyStr"; NSMutableString *str2 = [str1 copy]; NSMutableString *str3 = [str1 mutableCopy]; NSLog(@"str1:%p--%@",str1,str1); NSLog(@"str1:%p--%@",str2,str2); NSLog(@"str1:%p--%@",str3,str3);
2018-04-14 14:50:54.117652+0800 MutyCopy-Copy[2644:63575] str1:0x109a48068--copyStr 2018-04-14 14:50:54.117885+0800 MutyCopy-Copy[2644:63575] str1:0x109a48068--copyStr 2018-04-14 14:50:54.118010+0800 MutyCopy-Copy[2644:63575] str1:0x600000259a40--copyStr
1.str1,str2地址相同,而Str3地址不一样
2.NSString的copy是浅拷贝,copy返回的对象是不可变对象
3.mutablecopy是深拷贝web
*案例二:面试
NSMutableString * str1 = [NSMutableString stringWithString:@"mutableStr"]; NSMutableString * str2 = [str1 copy]; NSMutableString * str3 = [str1 mutableCopy]; NSLog(@"str:%p-----%@",str1,str1); NSLog(@"str:%p-----%@",str2,str2); NSLog(@"str:%p-----%@",str3,str3);
2018-04-14 15:04:50.092820+0800 MutyCopy-Copy[2685:70866] str:0x60000025b210-----mutableStr 2018-04-14 15:04:50.093059+0800 MutyCopy-Copy[2685:70866] str:0x60000022ca40-----mutableStr 2018-04-14 15:04:50.093217+0800 MutyCopy-Copy[2685:70866] str:0x60000025b540-----mutableStr
1.str1,str2,str3地址都不一样
2.NSMutableString对象copy与mutableCopy都是深拷贝
3.copy返回的对象是不可变对象编程
好比,咱们同时开启2条线程下载文件A,文件B.设计模式
注意:若是线程很是很是多,会发生什么状况?
cpu会在多个多线程之间进行调度,消耗大量的CPU资源.这样的话,每条线程被调度执行的频次会下降,线程执行效率下降.
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadFun) object:nil]; [thread start];
线程一启动,就会告诉CPU准别就绪,能够随时接受CPU调度.CPU调度当前线程以后,就会在线程thread中执行self的run方法安全
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
隐式建立并启动线程服务器
[self performSelectorInBackground:@selector(run) withObject:nil];
1.启动线程,start.就绪状态-->>运行状态.当新厂任务执行完毕,自动进入死亡状态
2.阻塞(暂停)线程,进入阻塞状态网络
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
3.强制中止线程
进入死亡状态多线程
注意:一旦线程中止了,就不能再次开启任务.
若是,多个线程访问同一块资源的话,会形成数据错乱的.
咱们应该怎么解决呢?并发
3.如图,
线程A和线程B同时访问资源变量Integer,
为了防止抢夺资源,
线程A在读取资源变量Integer以前先加一把锁,
而后读取Integer的数据并在线程A中完成数据操做(17+1=18),
而后把数据写入Integer中,
最后开锁Unlock.在线程A对Integer操做的过程当中,
线程B是无权访问Integer的,
只有线程A_Unlock后,线程B才能够访问资源变量Integer.
4.互斥锁使用格式
@synchronized(self){//须要锁定的代码}异步
注意: 锁定1分代码只用1把锁,用多把锁是无效的
5.互斥锁的优缺点
互斥锁的使用前提:多条线程抢夺同一块资源
优势:能有效防止因多线程抢夺资源形成的数据安全问题
缺点:须要消耗大量的CPU
6.nonatomic和atomic
atomic:
原子属性,为setter方法加锁(默认就是atomic)
线程安全,须要消耗大量的资源
nonatomic:
非原子属性,不会为setter方法加锁
非线程安全,适合内存小的移动设备
1.执行任务
GCD中有2个用来执行任务的函数
1.1用同步的方式执行任务
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); queue:队列 block:任务
1.2用异步的方式执行任务
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
1.3同步和异步的区别
同步:只能在当前线程中执行任务,不具有开启新线程的能力
异步:能够再新的线程中执行任务,具有开启新线程的能力
注意: 同步函数 + 主队列 == 死锁
dispatch_queue_t dispatch_get_global_queue( dispatch_queue_priority_t priority, 队列的优先级 unsigned long flags);
全局并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t = dispatch_queue_create(const char*label, 队列名称 dispatch_queue_attr_t attr); 队列属性,通常用NULL便可
2.使用主队列
放在主队列中的任务,都会放到主线程中执行
使用dispatch_get_main_queue()得到主队列
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 执行耗时的异步操做... dispatch_async(dispatch_get_main_queue(), ^{ 回到主线程,执行UI刷新操做 }); });
设定好延迟的时间后,它会先执行后边的代码,2秒后再调用self的run方法(而且不会卡主线程,在主线程调最后会回到主线程,在子线程调最后会回到子线程)
withObject:参数 afterDelay:延迟的时间 [self performSelector:@selector(run) withObject:nil afterDelay:2.0];
使用GCD函数(2秒后自动开启新线程 执行block中的代码,不会卡主当前的线程,在主/子线程调用均可以使用)
DISPATCH_TIME_NOW:如今开始的意 2.0 * NSEC_PER_SEC:设置的秒数(直接更改数字便可) dispatch_get_main_queue():主队列的意思 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 2秒后执行这里的代码... 在哪一个线程执行,跟队列类型有关 });
3.会卡住主线程
[NSThread sleepForTimeInterval:3]
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ 程序运行过程当中,永远只执行1次的代码(这里面默认是线程安全的) });
dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 执行1个耗时的异步操做 }); dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 执行1个耗时的异步操做 }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 等前面的异步操做都执行完毕后,回到主线程... });
1.异步函数+并发队列
1.建立队列(并发队列) dispatch_queue_t queue = dispatch_queue_create("com.baidu.www", DISPATCH_QUEUE_CONCURRENT); 异步函数 dispatch_async(queue, ^{ NSLog(@"1---%@",[NSThread currentThread]); });
2.异步函数+串行队列
1.建立队列(串行队列) dispatch_queue_t queue = dispatch_queue_create("com.baidu.www", DISPATCH_QUEUE_SERIAL); 异步函数 dispatch_async(queue, ^{ NSLog(@"1---%@",[NSThread currentThread]); });
3.同步函数+串行队列
1.建立队列(串行队列) dispatch_queue_t queue = dispatch_queue_create("com.baidu.www", DISPATCH_QUEUE_SERIAL); 同步函数 dispatch_sync(queue, ^{ NSLog(@"1---%@",[NSThread currentThread]); });
4.同步函数+并发队列
//得到全局并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 同步函数 dispatch_sync(queue, ^{ NSLog(@"1---%@",[NSThread currentThread]); });
5.异步函数+主队列
1.得到主队列 dispatch_queue_t queue = dispatch_get_main_queue(); 异步函数 dispatch_async(queue, ^{ NSLog(@"1---%@",[NSThread currentThread]); });
6.同步函数+主队列
1.得到主队列 dispatch_queue_t queue = dispatch_get_main_queue(); dispatch_sync(queue, ^{ NSLog(@"1---%@",[NSThread currentThread]); });
- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;
2.调用start方法开始执行操做
- (void)start;
一旦执行操做,就会调用target的sel方法
默认状况下,调用了start方法后并不会开一条新线程去执行操做,而是在当前线程同步执行操做;只有将NSOperation放到一个NSOperationQueue中,才会异步执行操做
+ (id)blockOperationWithBlock:(void (^)(void))block;
经过addExecutionBlock:方法添加更多的操做
- (void)addExecutionBlock:(void (^)(void))block;
只要NSBlockOperation封装的操做数 > 1,就会异步执行操做
- (void)addOperation:(NSOperation *)operation; - (void)addOperationWithBlock:(void (^)(void))block;
-(NSInteger)maxConcurrentOperationCount; - (void)setMaxConcurrentOperationCount:(NSInteger)cnt;
int main(int argc, char * argv[]) { NSLog(@"main"); return 0; }
int main(int argc, char * argv[]) { BOOL run = YES; do{ //执行各类任务,处理各类事件 }while(run); return 0; }
int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } }
Core Foundation中关于RunLoop的5个类:
CFRunLoopRef:它本身,也就表明一个RunLoop对象
CFRunLoopModeRef:RunLoop的运行模式
CFRunLoopSourceRef:事件源
CFRunLoopTimerRef:时间的触发器
CFRunLoopbaserverRef:观察者 监听CFRunLoopRef的状态
1.通知观察者,即将进入Loop
2.通知观察者,将要处理定时器
3.通知观察者,将要处理非基于端口的源
4.处理非基于端口的源
5.若是有基于端口的源准备好并处于等待状态,当即启动,跳到第9步
6.通知观察者,线程即将休眠
7.休眠,等待唤醒
8.通知观察者,线程刚被唤醒
9.处理唤醒时收到的消息,以后跳到第2步
10.通知观察者,即将推出Loop
HTTP协议规定:1个完整的由客户端发给服务器的HTTP请求中包含如下内容
文章来源于网络,若有侵权,请联系小编删除。