GCD 与 NSOperation 的区别 ?xcode
1. GCD 是基于 C 语言写的核心服务, 很是简单高效, 而 NSOperation 是基于 GCD 的一种封装,抽象出来的对象, 因此通常状况下对于任务的依赖和并发数没有要求的状况下, GCD 的效率更高, 开销更小多线程
2. 依赖关系,NSOperation能够设置两个NSOperation之间的依赖,第二个任务依赖于第一个任务完成执行,GCD没法设置依赖关系,不过能够经过dispatch_barrier_async来实现这种效果并发
3. KVO(键值对观察),NSOperation和容易判断Operation当前的状态(是否执行,是否取消),对此GCD没法经过KVO进行判断异步
4. 优先级,NSOperation能够设置自身的优先级,可是优先级高的不必定先执行,GCD只能设置队列的优先级,没法在执行的block设置优先级;async
5. 继承,NSOperation是一个抽象类实际开发中经常使用的两个类是NSInvocationOperation和NSBlockOperation,一样咱们能够自定义NSOperation,GCD执行任务能够自由组装,没有继承那么高的代码复用度;函数
总的来讲: 若是对于任务的并发数和任务之间的依赖关系没有要求, 能够直接使用 GCD, 不然使用 NSOperation 能够知足对任务的控制ui
GCDspa
GCD 面对的不是线程, GCD 面对的只有队列和任务这两个概念, 你不用管在哪一个线程, 只须要把任务按正确的同步/异步的方式添加进串行/并发队列便可线程
同步 异步code
主队列 死锁 不会开启新线程(顺序执行)
串行队列 在当前线程执行(顺序执行) 开启一个新的线程(顺序执行)
并发队列 在当前线程执行(顺序执行) 开启一个或多个线程(并发执行)
下面是例子
//异步 + 并行队列
- (
void
)asyncConcurrent{
//建立一个并行队列
dispatch_queue_t queue = dispatch_queue_create(
"标识符"
, DISPATCH_QUEUE_CONCURRENT);
NSLog(@
"---start---"
);
//使用异步函数封装三个任务
dispatch_async(queue, ^{
NSLog(@
"任务1---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任务2---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任务3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
}
结果: start end 3 2 1 // 开启3个新的线程 同时执行的 没有前后
//异步 + 串行队列
- (
void
)asyncSerial{
//建立一个串行队列
dispatch_queue_t queue = dispatch_queue_create(
"标识符"
, DISPATCH_QUEUE_SERIAL);
NSLog(@
"---start---"
);
//使用异步函数封装三个任务
dispatch_async(queue, ^{
NSLog(@
"任务1---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任务2---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任务3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
}
// 结果 start end 123 开启一个新的线程 顺序执行
//同步 + 并行队列
- (
void
)syncConcurrent{
//建立一个并行队列
dispatch_queue_t queue = dispatch_queue_create(
"标识符"
, DISPATCH_QUEUE_CONCURRENT);
NSLog(@
"---start---"
);
//使用同步函数封装三个任务
dispatch_sync(queue, ^{
NSLog(@
"任务1---%@"
, [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@
"任务2---%@"
, [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@
"任务3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
- (
void
)syncSerial{
//建立一个串行队列
dispatch_queue_t queue = dispatch_queue_create(
"标识符"
, DISPATCH_QUEUE_SERIAL);
NSLog(@
"---start---"
);
//使用异步函数封装三个任务
dispatch_sync(queue, ^{
NSLog(@
"任务1---%@"
, [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@
"任务2---%@"
, [NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@
"任务3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
}
- (
void
)asyncMain{
//获取主队列
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@
"---start---"
);
//使用异步函数封装三个任务
dispatch_async(queue, ^{
NSLog(@
"任务1---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任务2---%@"
, [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@
"任务3---%@"
, [NSThread currentThread]);
});
NSLog(@
"---end---"
);
}
});
以后呢,系统就会自动将 NSOperationQueue 中的 NSOperation 取出来,在新线程中执行操做
先看看NSInvocationOperation的使用:
1. 同步执行的 直接操做 不加入 queue
再看看NSBlockOperation:
22 NSBlockOperation *operation=[NSBlockOperation blockOperationWithBlock:^{ 23 NSLog(@"NSBlockOperation------%@",[NSThread currentThread]); 24 }]; 25 26 //添加操做 在子线程异步执行 27 [operation addExecutionBlock:^{ 28 NSLog(@"NSBlockOperation1------%@",[NSThread currentThread]); 29 }]; 30
// 在子线程 异步执行 31 [operation addExecutionBlock:^{ 32 NSLog(@"NSBlockOperation2------%@",[NSThread currentThread]); 33 }]; 34 35 //开启执行操做 36 [operation start];
// 设置最大并发数
// 1.建立队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 2.设置最大并发操做数
queue.maxConcurrentOperationCount =
1
;
// 串行队列
// queue.maxConcurrentOperationCount = 2; // 并发队列
// queue.maxConcurrentOperationCount = 8; // 并发队列
// 3.添加操做
[queue addOperationWithBlock:^{
for
(
int
i =
0
; i <
2
; i++) {
[NSThread sleepForTimeInterval:
2
];
// 模拟耗时操做
NSLog(@
"1---%@"
, [NSThread currentThread]);
// 打印当前线程
}
}];
[queue addOperationWithBlock:^{
for
(
int
i =
0
; i <
2
; i++) {
[NSThread sleepForTimeInterval:
2
];
// 模拟耗时操做
NSLog(@
"2---%@"
, [NSThread currentThread]);
// 打印当前线程
}
}];
[queue addOperationWithBlock:^{
for
(
int
i =
0
; i <
2
; i++) {
[NSThread sleepForTimeInterval:
2
];
// 模拟耗时操做
NSLog(@
"3---%@"
, [NSThread currentThread]);
// 打印当前线程
}
}];
[queue addOperationWithBlock:^{
for
(
int
i =
0
; i <
2
; i++) {
[NSThread sleepForTimeInterval:
2
];
// 模拟耗时操做
NSLog(@
"4---%@"
, [NSThread currentThread]);
// 打印当前线程
}
}];
NSBlockOperation最开始的任务是在主线程中执行的,再给NSBlockOperation添加的额外的任务是在子线程中执行的,程序自动帮助开启了子线程。
GCD队列和NSOperationQueue队列类型比较:
GCD的队列类型:
(1)并发队列:a.全局 b.本身建立的
(2)串行队列:a.主队列 b.本身建立的
NSOperationQueue队列类型:
(1)主队列[NSOperationQueue mainQueue],添加到主队列中的任务,都会在主线程中执行。
(2)其余队列(串行、并发),添加到其余队列中的任务,都会自动放在子线程中执行。
NSOperation默认是同步执行的。
建立一个 operation 直接 start 执行的话会在 main thread , 再添加额外的block 任务的时候会开启新的线程异步执行
建立一个 operation 和 queue 并把 operation 放进 queue 会自动放进子线程