- NSThread
- Runloop
- 线程间通信
- 线程间同步
- GCD
- NSOperation
NSThread,Runloop,线程间通信,线程间同步
GCD
NSOperation
GCD就是个block的封装,这在更复杂的场景下有点缺乏灵活性。IOS提供了NSOperation可以更灵活地支持线程间的切换,取消暂停任务等。
NSOperation相当于GCD更加面向对象的封装。可以将NSOperation类比成GCD里的block,NSOperationQueue类比成GCD里的队列。
NSOperation是个抽象类不能直接用,通常不需要程序员自己实现具体类,可以直接用系统提供的NSBlockOperation,NSInvocationOperation两个具体类供大家使用。但例如AFNetworking就自己实现了具体类,需要自己实现NSOperation的KVO属性:
isReady // 判断操作是否处于准备就绪状态,这个值和操作的依赖关系相关 isExecuting // 判断操作是否正在在运行 isFinished // 判断操作是否已经结束 isCancelled // 判断操作是否已经标记为取消
日常开发最常用的就是NSOperation+NSOperationQueue配合使用,能让多线程编程非常简单(就像段子将大象放进冰箱要几个步骤):
- 创建NSOperation对象,将需要执行的操作封装进去
- 创建NSOperationQueue队列
- 将NSOperation对象加入到NSOperationQueue队列中
NSOperationQueue用于管理operation的队列,底层使用libdispatch,可以设置最大并发数。
在NSOperationQueue中会自动忽略isAsynchronous(因为既然放入队列中就肯定是异步的),无法手动从队列中remove一个operation(但是可以调用operation的cancel方法取消一个operation),等所有operation执行完后(isFinished)会自动退出。
- (void)testNSOperationQueueOrder { NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; // 创建NSOperationQueue队列 // 创建NSOperation对象 NSBlockOperation *lastBlockOperation = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); NSLog(@"最后的任务"); }]; for (int i = 0; i < 5; ++i) { // 将NSOperation对象加入到NSOperationQueue对象中 NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ sleep(i); NSLog(@"第%d个任务",i); }]; [blockOperation addDependency:lastBlockOperation]; // 上面这行表示:所有任务都依赖这个前置任务,所以依次输出最后的任务,第0~4个任务 // 如果注释掉上面这行,输出是乱序的,最后的任务会穿插在第0~4个任务之间输出 [operationQueue addOperation:blockOperation]; } [operationQueue addOperation:lastBlockOperation]; }
可以设置各个NSOperation的优先级:
- (void)testNSOperationQueuePriority { NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init]; operationQueue.maxConcurrentOperationCount = 1; // 设置并发数为1,这样就等价于串行执行 NSBlockOperation *blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"低优先级任务"); }]; blockOperation1.queuePriority = NSOperationQueuePriorityLow; NSBlockOperation *blockOperation2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"高优先级任务"); sleep(1); }]; blockOperation2.queuePriority = NSOperationQueuePriorityHigh; NSBlockOperation *blockOperation3 = [NSBlockOperation blockOperationWithBlock:^{ // 无意义的任务,目的是卡个时间 }]; [blockOperation1 addDependency:blockOperation3]; [blockOperation2 addDependency:blockOperation3]; [operationQueue addOperation:blockOperation1]; [operationQueue addOperation:blockOperation2]; [operationQueue addOperation:blockOperation3]; // 依次输出高优先级任务,低优先级任务 }