这里介绍多线程中GCD和NSOperationQueue的使用。
GCD
主线程,任何需要刷新UI的操作都要在主线程中执行,耗时的操作放到子线程中。
//开辟线程时,要注意避免线程死锁,如在主线程中添加主线程,如
dispatch_sync(dispatch_get_main_queue(), ^{
});
//创建一个主线程
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//串行队列,主线程也是串行队列,里面的任务是依次执行的
//创建一个串行队列,第一个参数是队列的名称,第二个参数是队列的类型
dispatch_queue_t serialQueue = dispatch_queue_create("serial", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 5; i++) {
dispatch_async(serialQueue, ^{
NSLog(@"%@:串行任务 %d",serialQueue,i);
});
}
dispatch_queue_t serialQueue2 = dispatch_queue_create("serial2", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 5; i++) {
dispatch_async(serialQueue2, ^{
NSLog(@"%@:串行任务 %d",serialQueue2,i);
});
}
//要注意的是,串行队列内的任务是依次执行的,串行队列之间是并发的
log如下:
串行队列 串行队列之间的并发性
//并行队列,并行队列里的任务是并发性的
//创建一个并行队列,第一个参数是队列的名称,第二个参数是队列的类型
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrent", DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i < 5; i++) {
dispatch_async(concurrentQueue, ^{
NSLog(@"%@:并行任务 %d",concurrentQueue,i);
});
}
//还可以这样创建,第一个参数是苹果的优先级,第二个参数是苹果预留的参数,为以后去使用,目前没用到,写0
dispatch_queue_t concurrentQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 100; i++) {
dispatch_async(concurrentQueue2, ^{
NSLog(@"%@:并行任务 %d",concurrentQueue2,i);
});
}
队列组
队列组可以在组内的任务都执行完后通知开发者,在多任务监测中尤为方便
//队列组
//创建一个队列组
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, serialQueue, ^{
NSLog(@"%@",serialQueue);
});
dispatch_group_async(group, serialQueue2, ^{
NSLog(@"%@",serialQueue2);
});
dispatch_group_async(group, concurrentQueue, ^{
NSLog(@"%@",concurrentQueue);
});
dispatch_group_async(group, concurrentQueue2, ^{
NSLog(@"%@",concurrentQueue2);
});
//组内的任务都完成后发送通知
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"所有的任务都执行完毕");
});
NSOperation
NSOperation是对GCD的封装,完全面向对象,NSOperation和NSOperationQueue分别对应 GCD的任务和队列,有两个子类来封装线程任务
NSInvocationOperation
//创建一个NSInvocationOperation
NSInvocationOperation *invocation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImg) object:nil];
[invocation start]; //开始执行
NSBlockOperation
//创建NSBlockOperation
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"blockOperation: %@",[NSThread currentThread]);
}];
//添加多个block
for (int i = 0; i < 5; i++) {
[blockOperation addExecutionBlock:^{
[self loadImg];
NSLog(@"第 %d 次: %@",i,[NSThread currentThread]);
}];
}
//开始任务
[blockOperation start]; //start方法默认是同步执行的,要注意,添加进其他队列后就不要调用start()方法
队列
//队列,有主队列、其他队列,只要添加到队列,会自动调用任务的start()方法
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; //创建一个其他队列
[queue addOperation:blockOperation]; //添加进队列中
//默认为-1,即无限个并发数,设置为1时即相当于串行队列
//queue.maxConcurrentOperationCount = 1;
//依赖,当某个任务需要依赖其中一个任务执行完毕后再执行时,就可以使用依赖
//1.任务一:下载图片
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片 - %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1.0];
}];
//2.任务二:打水印
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"打水印 - %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1.0];
}];
//3.任务三:上传图片
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"上传图片 - %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1.0];
}];
//设置依赖,注意不要互相依赖,避免死锁
[operation2 addDependency:operation1]; //任务二依赖任务一
[operation3 addDependency:operation2]; //任务三依赖任务二
//创建队列并加入任务
NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
[queue2 addOperations:@[operation3,operation2,operation1] waitUntilFinished:NO];
其他方法:
NSOperation:
BOOL executing; //判断任务是否正在执行
BOOL finished; //判断任务是否完成
void (^completionBlock)(void); //用来设置完成后需要执行的操作
- (void)cancel; //取消任务
- (void)waitUntilFinished; //阻塞当前线程直到此任务执行完毕
NSOperationQueue:
NSUInteger operationCount; //获取队列的任务数
- (void)cancelAllOperations; //取消队列中所有的任务
- (void)waitUntilAllOperationsAreFinished; //阻塞当前线程直到此队列中的所有任务执行完毕
[queue setSuspended:YES]; // 暂停queue
[queue setSuspended:NO]; // 继续queue
线程同步
//线程同步,就是为了防止多个线程抢夺同一个资源造成数据安全问题所采取的措施
//互斥锁,加一个互斥锁,可以保证每次只有一个线程访问此代码块
@synchronized(self) {
}
回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
});
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
}];
网友评论