dispatch_barrier_async 函数的作用:如果任务是通过dispatch_barrier_async函数追加到concurrent queue中的,执行该任务时,其他的线程不执行,直到该任务完成,才恢复执行剩余的任务.
创建并行队列 : dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
创建串行队列 : dispatch_queue_t queue = dispatch_queue_create("tk.bourne.testQueue", NULL); //DISPATCH_QUEUE_SERIAL
NSOperation 是苹果公司对 GCD 的封装,完全面向对象,所以使用起来更好理解。 大家可以看到 NSOperation 和 NSOperationQueue 分别对应 GCD 的 任务 和 队列 。
*1//1.创建NSInvocationOperation对象
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
//2.开始执行
[operation start];
*2//1.创建NSBlockOperation对象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
//2.开始任务
[operation start];
NSBlockOperation 还有一个方法:addExecutionBlock: ,通过这个方法可以给 Operation 添加多个执行 Block。这样 Operation 中的任务 会并发执行,它会 在主线程和其它的多个线程 执行这些任务
//1.创建一个其他队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.创建NSBlockOperation对象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
//3.添加多个Block
for(NSInteger i = 0; i < 5; i++) {
[operation addExecutionBlock:^{
NSLog(@"第%ld次:%@", i, [NSThread currentThread]);
}];
}
//4.队列添加任务
[queue addOperation:operation];
OK, 这时应该发问了,大家将 NSOperationQueue 与 GCD的队列 相比较就会发现,这里没有并行队列,那如果我想要10个任务在其他线程串行的执行怎么办?
这就是苹果封装的妙处,你不用管串行、并行、同步、异步这些名词。NSOperationQueue 有一个参数 maxConcurrentOperationCount 最大并发数,用来设置最多可以让多少个任务同时执行。当你把它设置为 1 的时候,他不就是串行了嘛!
NSOperationQueue 还有一个添加任务的方法,- (void)addOperationWithBlock:(void (^)(void))block; ,这是不是和 GCD 差不多?这样就可以添加一个任务到队列中了,十分方便
NSOperation 有一个非常实用的功能,那就是添加依赖。比如有 3 个任务:A: 从服务器上下载一张图片,B:给这张图片加个水印,C:把图片返回给服务器。这时就可以用到依赖了
operation2.addDependency(operation1) //添加依赖关系
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) {
//需要执行的代码块
}
同步执行:我们可以使用多线程的知识,把多个线程都要执行此段代码添加到同一个串行队列,这样就实现了线程同步的概念。当然这里可以使用 GCD 和 NSOperation 两种方案
//GCD
//需要一个全局变量queue,要让所有线程的这个操作都加到一个queue中
dispatch_sync(queue, ^{
NSInteger ticket = lastTicket;
[NSThread sleepForTimeInterval:0.1];
NSLog(@"%ld - %@",ticket, [NSThread currentThread]);
ticket -= 1;
lastTicket = ticket;
});
//NSOperation & NSOperationQueue
//重点:1. 全局的 NSOperationQueue, 所有的操作添加到同一个queue中
// 2. 设置 queue 的 maxConcurrentOperationCount 为 1
// 3. 如果后续操作需要Block中的结果,就需要调用每个操作的waitUntilFinished,阻塞当前线程,一直等到当前操作完成,才允许执行后面的。waitUntilFinished 要在添加到队列之后!
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSInteger ticket = lastTicket;
[NSThread sleepForTimeInterval:1];
NSLog(@"%ld - %@",ticket, [NSThread currentThread]);
ticket -= 1;
lastTicket = ticket;
}];
[queue addOperation:operation];
[operation waitUntilFinished];
//后续要做的事
从其他线程回到主线程的方法:
1. [self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:NO];
2. dispatch_async(dispatch_get_main_queue(), ^{
});
3. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
}];