上篇文章寫到GCD,GCD的優(yōu)點(diǎn)是我們只需要定義想要執(zhí)行的任務(wù)并追加到適當(dāng)?shù)腄ispatch Queue中,GCD負(fù)責(zé)生成線程、計(jì)劃執(zhí)行任務(wù)并管理線程的生命周期,其線程管理是作為系統(tǒng)的一部分來實(shí)現(xiàn)的,因此可統(tǒng)一管理,所以效率很高,而且形式上十分簡潔。
GCD看似很完美了,但是GCD是基于C語言開發(fā)的,而NSOperation是基于GCD且面向?qū)ο蟮募夹g(shù),比GCD多了一些簡單實(shí)用的功能。雖然NSOperation會增加額外的開銷,但是更加靈活。NSOperation對應(yīng)GCD的任務(wù),NSOperationQueue對應(yīng)GCD的隊(duì)列。
NSOperation
NSOperation是一個抽象類,我們創(chuàng)建需要執(zhí)行的任務(wù)時,需要使用其子類。Apple為我們定義了兩個NSOperation的子類:NSInvocationOperation和NSBlockOperation,另外我們可以自定義NSOperation的子類。
NSOperationQueue
有兩種NSOperationQueue:
主隊(duì)列:通過下面方法獲取,放到主隊(duì)列的任務(wù)在主線程執(zhí)行。
NSOperationQueue*queue = [NSOperationQueuemainQueue];
非主隊(duì)列:
NSOperationQueue*queue = [[NSOperationQueuealloc]init];
非主隊(duì)列既可以并發(fā)執(zhí)行任務(wù)也可以串行執(zhí)行任務(wù),通過設(shè)置最大并發(fā)數(shù)來控制。最大并發(fā)數(shù)默認(rèn)為-1,表示不受限制,如果最大并發(fā)數(shù)為1則是串行隊(duì)列。非主隊(duì)列無論是并發(fā)隊(duì)列還是串行隊(duì)列都不在主線程中執(zhí)行。
NSOperation可以調(diào)用start方法來執(zhí)行任務(wù),而不用加入到NSOperationQueue中,但是該任務(wù)將會在當(dāng)前線程同步執(zhí)行。
NSInvocationOperation
NSInvocationOperation *io =?[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest) object:nil];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:io];
- (void)invocationTest {
for(int i =0; i <100; i++) {
NSLog(@"mainThread: %@, currentThread: %@", [NSThreadmainThread], [NSThreadcurrentThread]);
}
}
NSBlockOperation
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^ {
for(int i =0; i <100; i++) {
NSLog(@"%@",[NSThread currentThread]);
}
}];
[queue addOperation:bo];
自定義非并發(fā)的NSOperation子類:
我們要自定義初始化方法,并重寫- (void)main {};方法,在此方法中需要能相應(yīng)取消時間。
其余方法:
NSBlockOperation的addExecutionBlock方法:
NSBlockOperation *blockOperation = [NSBlockOperationblock OperationWithBlock:^{
NSLog(@"block1 : currentThread: %@", [NSThread currentThread]);
sleep(3);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"block2 : currentThread: %@", [NSThread currentThread]);
sleep(3);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"block3 : currentThread: %@", [NSThread currentThread]);
sleep(3);
}];
[blockOperation start];
結(jié)果:Block1是在主線程中執(zhí)行的,block2和block3不是。
添加依賴:
[io addDependency:bo];
io會在bo執(zhí)行完后執(zhí)行,不同隊(duì)列的operation之間可以添加依賴。
可通過下面方法執(zhí)行operation完畢后的操作。
io.completionBlock= ^{
NSLog(@"finish");
};
我們經(jīng)常需要在非主線程完成后回到主線程刷新UI:
NSBlockOperation *bo = [NSBlockOperation blockOperationWithBlock:^ {
for(inti =0; i <100; i++) {
NSLog(@"%@",[NSThread currentThread]);
}
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"=====%@",[NSThreadcurrentThread]);
}];;
}];
暫停任務(wù):
queue.suspended = YES;
恢復(fù)任務(wù):
queue.suspended=NO;
取消所有任務(wù),一旦取消不可逆
[queue cancelAllOperations];
暫停和取消只能暫停或取消處于等待狀態(tài)的任務(wù),不能暫停或取消正在執(zhí)行中的任務(wù)