多线程与RunLoop

it2022-05-05  129

iOS开发中的多线程

一个iOS程序,默认开启1条线程--主线程orUI线程 主线程主要作用:         显示/刷新UI界面         处理UI事件(点击、滚动、拖拽事件等) 主线程使用注意:          别将耗时操作放在主线程          耗时操作应放在子线程(后台线程or非主线程)

iOS中多线程实现方案

   

1.pthread -- POSIX Thread    iPhone2.0

创建子线程:pthread_create  

2. NSThread -- 一个NSThread对象代表一条线程

创建和启动线程     [[ NSThread alloc] initWithTarget:self selector:@selector(run:) object:nil];     [thread start];   主线程相关方法     + (NSThread *)mainThread; //获得主线程     - (BOOL)isMainThread; //判断是否为主线程     + (BOOL)isMainThread;   其他用法 其他创建线程方式     创建线程后自动启动         [NSThread  detachNewThreadSelector:toTarget:withObject:];     隐式创建线程后自动启动         [self  performSelectorInBackground:withObject:]; // NSObject的方法   线程状态  阻塞(暂停)线程   + (void)sleepUntilDate:   + (void)sleepForTimeInterval: 强制停止线程   + (void)exit   //进入死亡状态   注意:一旦线程停止,就不能再次开启任务   线程同步     互斥锁 -- 线程同步     @synchronized(锁对象 eg: self){//加锁         ....需要锁住的代码         .... 一份代码只能对应一把锁     }//解锁           线程间通信      

 

3.GCD -- Grand Central Dispatch "牛逼的中枢调度器"

任务和队列     队列:用来存放任务     GCD步骤:定制任务-->将任务添加到队列 (GCD自动取出队列中任务,放到对应线程执行)     任务的取出遵从:FIFO原则   同步:在当前线程中执行(不具备开启新线程能力) 异步:在另一条线程中执行   --------------------------- 全局并发队列: dispatch_get_global_queue 串行队列:     1) dispatch_queue_create();   在MRC中调用dispatch_release(queue)     2) 使用主队列(跟主线程相关联的队列) --  dispatch_get_main_queue             主队列是GCD自带的特殊串行队列;             放在主队列中的任务,都会放到主线程中执行   GCD其他用法   只执行一次     dispatch_once   队列组     

4. NSOperation

1> 基本使用

NSOperation和NSOperationQueue实现多线程   2>NSOperation(抽象类)子类: 》NSInvocationOperation 创建并启动操作对象: [[NSInvocationOperation alloc]initWithTarget:selector:object]; [operation start]; //默认情况下不会创建新线程;除非放到队列中   》NSBlockOperation [NSBlockOperation blockOperationWithBlock:]; [operation start];//默认情况下不会创建新线程;除非放到队列中   [operation addExecutionBlock:];//当operation中的操作个数>1就会开启新线程 》自定义子类 必须实现main方法,在main方法中实现具体操作 - (void)main {     ...... } 3> NSOperationQueue [[NSOperationQueue alloc]init]; [queue addOperation:]; //自动执行操作,自动开启线程;默认是并发执行 [queue addOperationWithBlock:] *  最大并发数设置 - (void)setMaxConcurrentOperationCount:(NSInteger)cnt; 一般2-3并发数,5以内   队列的取消、暂停、恢复 - (void)cancelAllOperations - (void)setSuspended:BOOL // YES代表暂停,NO代表恢复 * 设置依赖 [operationB addDependency:operationA]; // 操作B依赖于操作A 也可以在不同队列的操作间设置依赖 注意:不能相互依赖   操作的监听 operation.completionBlock=^{};  

RunLoop

不能显示的创建管理runloop,每个thread自己就会有一个runloop,在当前线程调用 currentRunLoop方法就能得到线程对应的runloop

作用

。使程序一直运行并接收用户输入

。决定程序在何时处理那些Event

。调用解耦(--消息队列)

。节省CPU时间

RunLoops in Cocoa

Cocoa中跟RunLoop有关的类

NSTimer,UIEvent,Autorelease,NSDelayedPerforming,NSThreadPerformAddition

CADisplayLink,CATransition,CAAnimation,dispatch_get_main_queue(), NSURLConnnection.....

 调用堆栈中

Xcode调试时调用堆栈中以__CFRunLoopxxxxxx的函数

RunLoop机制

》CFRunLoopTimer

RunLoopTimer的封装

+ (NSTimer *)timerWithTimeInterval: invocation: repeats:

+ (NSTimer *)scheduledTimerWithInterval: invocation: repeats:

- (void)performSelector: withObject: afterDelay: inModes:

+ (CADisplayLink *)dispalyLinkWithTarget: selector:

- (void)addToRunLoop: forMode:

》CFRunLoopSource

Source是RunLoop的数据源抽象类(protocol)

RunLoop定义了两个Version的Source:

  1. Source0:处理App内部事件、App自己负责管理(触发)如UIEvent、CFSocket

  2. Source1:由RunLoop和内核管理、Mach port驱动,如CFMachPort,CFMessagePort

》CFRunLoopObserver

 

》CFRunLoopMode

。RunLoop在同一时间段只能且必须在一种特定Mode下Run

。更换Mode时,需要停止当前loop,然后重启新loop

。Mode是iOS App滑动顺畅的关键

NSDefalutRunLoopMode

  默认状态、空闲状态

UITrackingRunLoopMode

  滑动ScrollView时

UIInitializationRunLoopMode

  私有,App启动时

NSRunLoopCommonModes

  以上一个或几个的组合(可以自己定义组合)

 

ScrollView滑动时RunLoopMode的切换:NSDefalutRunLoopMode -开始滑动-> UITrackingRunLoopMode -停止滑动-> NSDefalutRunLoopMode

》GCD中dispatch到main queue的block被分发到main RunLoop执行,dispatch_after同理

》RunLoop的挂起和唤醒

》AFNetworking中创建了一个单例network 线程,用RunLoop让这个线程常驻(不会执行完某次网络操作就杀掉)

这样子是否只开了一个网络请求子线程?

 

转载于:https://www.cnblogs.com/shanhua/p/4770209.html


最新回复(0)