参考资料:
在 GCD 中,有两个概念很重要,那就是任务和队列。
- dispatch_queue_t queue = dispatch_get_main_queue();
- //串行队列
- dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
- dispatch_queue_t queue = dispatch_queue_create("MyQueue", DISPATCH_QUEUE_SERIAL);
- //并行队列
- dispatch_queue_t queue = dispatch_queue_create("MyQueue", DISPATCH_QUEUE_CONCURRENT);
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- dispatch_sync(queue, ^{
- //your code
- NSLog(@"%@", [NSThread currentThread]);
- });
异步任务:不会阻塞当前线程 (ASYNC)
- dispatch_async(queue, ^{
- //your code
- NSLog(@"%@", [NSThread currentThread]);
- });
- //创建队列组
- dispatch_group_t group = dispatch_group_create();
- //创建队列
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- //使用队列组方法只有异步方法
- //执行3次循环
- dispatch_group_async(group, queue, ^{
- for (int i = 0; i < 3; ++i) NSLog(@"%@", task 1);
- });
- //主队列中执行循环2次
- dispatch_group_async(group, dispatch_get_main_queue(), ^{
- for (int i = 0; i < 2; ++i) NSLog(@"%@", task 2);
- });
- //执行4次循环
- dispatch_group_async(group, queue, ^{
- for (int i = 0; i < 4; ++i) NSLog(@"%@", task 3);
- });
- //3个线程任务完成后自动通知
- dispatch_group_notify(group, dispatch_get_main_queue(), ^{
- NSLog(@"Complete !");
- });
- dispatch_barrier_async(_queue: dispatch_queue_t, _block: dispatch_block_t);
这个方法的重点是你传入的 queue,当你传入的是通过 DISPATCH_QUEUE_CONCURRENT 参数自己创建的 queue 时,这个方法会阻塞这个 queue(注意,是阻塞 queue,而不是当前线程),直到这个 queue 中在_block 之前的任务被执行完后才开始执行自己,自己执行完毕后,才取消这个 queue 的阻塞,使这个 queue 后面的任务得以被执行。但是如果你传入的是其它的队列,那么这个函数和 dispatch_async 没有区别了
- dispatch_barrier_sync(_queue: dispatch_queue_t, _block: dispatch_block_t);
这个方法的使用和上面的一样,不同的是这个方法不仅阻塞队列,还会阻塞当前线程。如果你传入的是其它的 queue,那么它就和 dispatch_sync 一样了。
NSOpreation 是 Apple 对 GCD 的再封装,完全面向对象。NSOperation 和 NSOpreationQueue 分别对应 GCD 的任务和队列。
我们需要做的就是将任务封装到 NSOperation 对象中,再将此任务添加到 NSOperationQueue 对象中即可。具体操作往下看吧。
需要说明的是,NSOperation 只是一个抽象类,不能封装任务。我们用它的两个子类来封装任务,这两个子类分别是:NSInvocationOperation 和 NSBlockOperation。创建一个 operation 后,需要调用 start 方法来启动任务,它会默认在当前队列中同步执行。取消任务需要调用 cancel 方法。
- //创建NSInvocationOperation对象
- NSInvocationOperation * operation = [[NSInvocationOperation alloc] initWithTarget: self selector: @selector(run) object: nil];
- //执行任务
- [operation start];
- //创建NSBlockOperation对象
- NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock: ^{
- NSLog(@"%@", [NSThread currentThread]);
- }];
- //开始任务
- [operation start];
之前说过,这样封装的任务默认会在当前线程同步执行。但是 NSBlockOperation 还有个方法是 addExecutionBlock:,通过这个方法可以给 Operation 添加多个执行 Block。这样 Operation 中的任务会并发执行,它会在主线程和其它多个线程执行这些任务。
- //创建NSBlockOperation对象
- NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock: ^{
- NSLog(@"%@", [NSThread currentThread]);
- }];
- //添加多个Block
- for (int i = 0; i < 5; ++i) { [operation addExecutionBlock: ^{
- NSLog(@"task %d: %@", i, [NSThread currentThread]);
- }];
- }
- //开始任务
- [operation start];
注意:addExecutionBlock 方法必须在 start 之前添加,否则会报错。
这里的队列分为主队列和其他队列。只要任务添加到队列,就会自动调用 start 方法。
- NSOperationQueue * queue = [NSOperationQueue mainQueue];
- //创建一个非主队列
- NSOperationQueue * queue = [[NSOperationQueue alloc] init];
- //创建NSBlockOperation对象
- NSBlockOperation * operation = [NSBlockOperation blockOperationWithBlock: ^{
- NSLog(@"%@", [NSThread currentThread]);
- }];
- //添加多个Block
- for (int i = 0; i < 5; ++i) { [operation addExecutionBlock: ^{
- NSLog(@"task %d : %@", i, [NSThread currentThread]);
- }];
- }
- //添加任务到队列中
- [queue addOperation: operation];
NSOperationQueue 中有一个参数 maxConcurrentOperationCount,用它来控制并发数量,如果并发数量为 1,那么就是串行,否则是并行。NSOperationQueue 中还有一个添加任务的方法 addOperationWithBolck:(void(^)(void))block。
NSOperation 中可以为任务添加依赖。比如 A 任务完成后才执行 B 任务,B 任务完成后执行 C 任务。
- //mission 1
- NSBlockOperation * operation1 = [NSBlockOperation blockOperationWithBlock: ^{
- NSLog(@"task 1 : %@", [NSThread currentThread]); [NSThread sleepForTimeInterval: 1.0f];
- }];
- //mission 2
- NSBlockOperation * operation2 = [NSBlockOperation blockOperationWithBlock: ^{
- NSLog(@"task 2 : %@", [NSThread currentThread]); [NSThread sleepForTimeInterval: 1.0f];
- }];
- //mission 3
- NSBlockOperation * operation3 = [NSBlockOperation blockOperationWithBlock: ^{
- NSLog(@"task 3 : %@", [NSThread currentThread]); [NSThread sleepForTimeInterval: 1.0f];
- }];
- //设置依赖
- [operation2 addDependency: operation1]; [operation3 addDependency: operation2];
- //创建队列并加入任务
- NSOperationQueue * queue = [[NSOperationQueue alloc] init]; [queue addOperations: @ [operation3, operation2, operation1] waitUntilFinished: NO];
注意别互相依赖,会导致死锁
可以使用 removeDependency 来解除依赖关系
依赖只与任务有关,与队列无关
- //3秒后自动调用self的run方法,并传参数@"abc"
- [self performSelector: @selector(run: ) withObject: @"abc"afterDelay: 3];
- dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
- double delay = 3;
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queue, ^{
- //your code , execute after 3sec
- });
- [NSTimer scheduledTimerWithTimeInterval: 3.0 target: self selector: @selector(run: ) userInfo: @"abc", repeats: NO];
标准实现方法
- @interface Tool: NSObject < NSCopying > +(instancetype) shareTool;@end@implementation Tool static id _instance; + (instancetype) shareTool {
- static dispatch_once_t onceToken;
- dispatch_once( & onceToken, ^{
- _instance = [[Tool alloc] init];
- });
- return _instance;
- }@end
- [self performSelectorOnMainThread: @selector(run) withObject: nil waitUntilDone: NO];
- dispatch_async(dispatch_get_main_queue(), ^{});
- [[NSOperationQueue mainQueue] addOperationWithBlock: ^{}];
来源: http://lib.csdn.net/article/ios/43478