一个iOS程序,默认开启1条线程--主线程orUI线程
主线程主要作用:
显示/刷新UI界面
处理UI事件(点击、滚动、拖拽事件等)
主线程使用注意:
别将耗时操作放在主线程
耗时操作应放在子线程(后台线程or非主线程)
创建子线程:pthread_create
创建和启动线程
[[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){//加锁
….需要锁住的代码
….一份代码只能对应一把锁
}//解锁
线程间通信
任务和队列
队列:用来存放任务
GCD步骤:定制任务-->将任务添加到队列 (GCD自动取出队列中任务,放到对应线程执行)
任务的取出遵从:FIFO原则
同步:在当前线程中执行(不具备开启新线程能力)
异步:在另一条线程中执行
---------------------------
全局并发队列:dispatch_get_global_queue
串行队列:
1) dispatch_queue_create(); 在MRC中调用dispatch_release(queue)
2) 使用主队列(跟主线程相关联的队列) -- dispatch_get_main_queue
主队列是GCD自带的特殊串行队列;
放在主队列中的任务,都会放到主线程中执行
GCD其他用法
只执行一次
dispatch_once
队列组
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,每个thread自己就会有一个runloop,在当前线程调用 currentRunLoop方法就能得到线程对应的runloop
。使程序一直运行并接收用户输入
。决定程序在何时处理那些Event
。调用解耦(--消息队列)
。节省CPU时间
Cocoa中跟RunLoop有关的类
NSTimer,UIEvent,Autorelease,NSDelayedPerforming,NSThreadPerformAddition
CADisplayLink,CATransition,CAAnimation,dispatch_get_main_queue(), NSURLConnnection…..
调用堆栈中
Xcode调试时调用堆栈中以__CFRunLoopxxxxxx的函数
RunLoopTimer的封装
+ (NSTimer *)timerWithTimeInterval: invocation: repeats:
+ (NSTimer *)scheduledTimerWithInterval: invocation: repeats:
- (void)performSelector: withObject: afterDelay: inModes:
+ (CADisplayLink *)dispalyLinkWithTarget: selector:
- (void)addToRunLoop: forMode:
Source是RunLoop的数据源抽象类(protocol)
RunLoop定义了两个Version的Source:
1. Source0:处理App内部事件、App自己负责管理(触发)如UIEvent、CFSocket
2. Source1:由RunLoop和内核管理、Mach port驱动,如CFMachPort,CFMessagePort
。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让这个线程常驻(不会执行完某次网络操作就杀掉)
这样子是否只开了一个网络请求子线程?
手机扫一扫
移动阅读更方便
你可能感兴趣的文章