操作与队列

    xiaoxiao2021-03-26  27

    IOS的三种多线程技术(多线程技术的目的:为了在一个CPU上实现快速切换) 1.NSThread 1. [NSThread detachNewThreadSelector:@selector(threadMain:)toTarget:self WithObject:nil]; 这个创建方法一旦创建成功,线程马上运行 2. NSThread *t=[NSThread alloc]initWithTarget:self selector:@selector(threadMain3:) object: [NSNumber numberWithFloat:2]]; [t start]; init方式创建的线程不会自动运行,只有主动启动才可以 a. 使用NSThread对象建立一个线程非常方便, b. 但是要使用NSThread管理多个线程非常困难,不推荐使用; c. 技巧:使用[NSThread currentThread]跟踪任务所在线程,适用于这三种技术

    NSObject的多线程方法 1.开启后台执行任务的方法 -(void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg; 2.在后台线程中通知主线程执行任务的方法 -(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

    特点: 使用简单,量级轻,但是不能控制线程数量以及执行顺序

    注意事项: 1. NSObject的多线程方法使用的时NSThread的多线程技术,而NSThread的多线程技术不会自动使用@autoreleasepool 2.在使用NSObject或NSThread的多线程技术时,如果涉及到对象分配.需要手动添加@autoreleasepool

    2.NSOperation/NSOperationQueue

    1. NSOperation *myOperation=[[NSOperation alloc]init]; NSOperationQueue* myOperationQueue=[[NSOperationQueue alloc]init]; [myOperationQueue addOperation: myOperation]; 2. NSInvocationOperation* invocationOperation=[[NSInvocationOperation alloc]initWithTarget:aObj selector:@selector(fun:) object:nil]; NSOperationQueue * operationQueue=[[NSOperationQueue alloc]init]; [operationQueue addOperation : invocationOperation]; 3.NSOperationQueue * operationQueue=[[NSOperationQueue alloc]init]; NSBlockOperation* blockOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@“ [NSThread currentThread]==%@”,[NSThread currentThread]); }]; [operationQueue addOperation: blockOperation]; 3比2使用起来更加灵活

    a. 是使用GCD实现的是一套OC的API b. 是面向对象的线程技术 c. 提供了一些在GCD中不容易实现的特性,如: 限制最大并发数量,,,操作之间的依赖关系 d. GCD提供了更加底层的控制,而操作队列则在GCD之上实现了一些方便的功能 e. 队列:主队列 (运行在主线程上) 自定义队列 (在后台执行) f. 一旦将操作添加到队列,操作就会立即被调度执行 g. 利用addDependency可以指定操作之间的彼此依赖关系(注意不要出现循环依赖) h. setMaxConcurrentOperationCount设置同时并发的线程数量(能够有效地降低CPU和内存的开销,而且这一功能GCD不容易实现) i. 从本质上来看,操作队列的性能回避GCD略低,不多大多数情况下这点负面影响可以忽略不计,操作队列是并发编程的首选工具 j. AFN,底层用GCD开发,开发接口是NSOperation的

    3.GCD—Grand Central Dispatch(大中央调度) 1.基本思想: 将操作放到队列中去执行 2.GCD的函数都是以dispatch(分派,调度)开头的 3.队列: (队列不是线程,也不表示对应的cpu,就是负责调度的,谁空闲就把任务给谁) dispatch_queue_t a.串行队列,队列中的任务只会顺序执行 b.并行队列,队列中的任务通常会并发执行 4.操作: dispatch_async 异步操作,会并发执行,无法确定任务的执行顺序 dispatch_sync 同步操作,会依次顺序执行,能够决定任务的执行顺序 1. 是基于C语言的底层API 2. 用Block定义任务,使用起来非常灵活便捷 3. 提供了更多的控制能力以及操作队列中所不能使用的底层函数

    不同队列中嵌套同步操作的结果:

    这里有两个系统已经创建好的队列: a. 全局队列(并行队列) b. 主队列(串行队列,主线程上的任务分配到主队列上) 注: 1. 每一个应用程序对应唯一一个主队列(多线程中,UI的更新在主队列上) 2. 主队列中的操作都应该在主线程上顺序执行的,不存在异步的概念(那么到底能不能异步地分配任务给主队列???) 3. 如果把主线程中的操作看成一个大的Block,除非主线程被用户杀掉,否则永远不会结束,也就是在主队列中添加的同步操作永远不会被执行,会死锁

    同步的分配任务给全局队列

    这个函数会阻塞到代码块里面的所有内容都执行完毕才会返回 dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{ NSLog(@“global_queue currentThread==%@”,[NSThread currentThread]); int i=0; while(i<5) { NSLog(@“dispatch_get_global_queue i=%d”,i++); sleep(1); } });

    异步的分配任务给全局队列(然后全局队列再去自己调度分配任务)

    这个函数不会阻塞,会立即返回

    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{ NSLog(@“global_queue currentThread==%@”,[NSThread currentThread]); int i=0; while(i<5) { NSLog(@“dispatch_get_global_queue i=%d”,i++); sleep(1); } 创建自己的串行队列(并行:DISPATCH_QUEUE_CONCURRENT) dispatch_queue_t myqueue=dispatch_queue_creat(“mike’s queue”,DISPATCH_QUEUE_SERIAL); dispatch_async (myqueue,^{ int i=0; while(i<3) { NSLog(@“myqueue i=%d”,i++); sleep(1); } });

    4.设置队列的属性 把第一个队列的属性设置成第二队列的属性(这里设置优先级为最高dispatch_set_target_queue(myqueue,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0))

    5.暂停和重启一个任务队列 dispatch_suspend(myqueue); dispatch_resume(myqueue);

    6.GCD的队列 1.GCD公开有5个不同的队列,运行在主线程中的主队列,3个不同优先级的后台队列,以及一个优先级更低的后台队列(用于I/O) 2. 自定义队列:串行和并行队列,自定义队列非常强大,建议在开发中使用.在自定义队列中被调度的所有Block最终都将被放入到系统的全局队列中和线程池中 3. 不建议使用不同优先级的队列,因为如果设计不当,可能会出现优先级反转,即低优先级的操作阻塞高优先级的操作 4. GCD在后端管理着一个线程池,GCD不仅决定着代码块将在哪个线程被执行,它还根据可用的系统资源对这些线程进行管理,从而让开发者从线程管理的工作中解放出来,通过集中的管理线程,缓解大量线程被创建的问题

    /// 线程间的异步通信: 1.同步的向主队列分配任务(同步向主线程进行通信)

    dispatch_sync(dispatch_get_main_queue(),^{ NSLog(@“dispatch_get_main_queue currentThread==%@”,[NSThread currentThread]); });

    6.串行队列: 同步任务,不需要新建线程 异步任务,需要一个子线程,线程的创建和回收不需要程序员参与,是最安全的一个选择 并行队列: 同步任务,不需要创建线程 异步任务,有多少个任务,就开N个线程(并不是开多少个线程) 注:无论什么队列和什么任务,线程的创建和回收不需要程序员参与,这个工作是由队列负责的

    2.异步的向主队列分配任务(异步地向主线程进行通信)

    dispatch_async(dispatch_get_main_queue(),^{ NSLog(@“dispatch_get_main_queue currentThread==%@”,[NSThread currentThread]); });

    主线程中需要加入

    while(1)

    { [[NSRunLoop currentRunLoop] run]; }

    /

    RUN LOOP 1.简介: 1.Run Loop 提供了一种异步执行代码的机制,不能并行执行任务 2.在主队列中,Main Run Loop直接配合任务的执行,负责处理UI事件,计时器,以及 其他内核相关的事件 3.Run Loop的主要目的是保证程序执行的线程不会被系统终止

    2.工作特点: 1.当有事件发生时,Run Loop会根据具体的事件类型通知应用程序做出响应 2.当没有事件发生时,Run Loop会进入休眠状态,从而达到省电的目的 3.当事件再次发生时,Run Loop会被重新唤醒,处理事件

    IOS的主线程默认已经配置好了Run Loop,其他线程默认情况下没有设置Run Loop 一般在开发中很少会主动创建RunL

    oop,而通常会把事件添加到Runloop中

    / 单例

    单例模式是一种常用的软件设计模式

    通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便实现对实例个数的控制并节约系统资源

    如果希望系统中某个类的对象只存在一个,单例模式就是最好的解决方案

    IOS中最常见的单例就是UIApplication

    sharedXXX,mainXXX

    单例的实现方法 1.重写allocWithZone方法 allocWithZone方法是对象分配内存空间时,最终会调用的方法,重写该方法,保证只会分配一个内存空间 2.建立sharedXXX类方法,便于其他类访问

    小结: 单例优点是可以阻止其他对象实例化单例对象的副本,从而确保所有对象都访问唯一实例,但是缺点是单例对象一旦建立,对象指针是保存在静态区的,单例对象在堆中分配的内存空间会在应用程序终止后才会被释放;另外,只有确实需要唯一使用的对象才需要考虑单例模式,不要滥用单例

    /// 自动释放池的工作原理 1.标记为autorelease的对象在出了作用域范围后,会被添加到最近一次创建的自动释放池中 2.当自动释放池被销毁或耗尽时,会向自动释放池中的所有对象发送release消息 3.每个线程都需要有@autoreleasepool,否则可能会出现内存泄露,但是使用NSthread多线程技术,并不会为后台线程创建自动释释放池

    转载请注明原文地址: https://ju.6miu.com/read-450011.html

    最新回复(0)