NSOperation的使用
NSOperation是個(gè)抽象類,并不具備封裝操作的能力,必須使用它的子類,使用NSOperation子類的方式有3種
- NSBlockOperation
//1. 封裝任務(wù)
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1---%@", [NSThread currentThread]);
}];
//2.追加其它任務(wù)
//注意: 在沒(méi)有隊(duì)列的情況下, 如果給BlockOperation追加其它任務(wù), 那么其它任務(wù)會(huì)在子線程中執(zhí)行
[op1 addExecutionBlock:^{
NSLog(@"2---%@", [NSThread currentThread]);
}];
[op1 addExecutionBlock:^{
NSLog(@"3---%@", [NSThread currentThread]);
}];
//3.啟動(dòng)任務(wù)
[op1 start];
注意:
默認(rèn)情況下,調(diào)用了start方法后并不會(huì)開(kāi)一條新線程去執(zhí)行操作,而是在當(dāng)前線程同步執(zhí)行操作,只有將NSOperation放到一個(gè)NSOperationQueue中,才會(huì)異步執(zhí)行操作NSInvocationOperation
//1.封裝任務(wù)
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
//2.要想執(zhí)行任務(wù)必須調(diào)用start
[op1 start];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2) object:nil];
[op2 start];
}
- (void)run
{
NSLog(@"%@", [NSThread currentThread]);
}
- (void)run2
{
NSLog(@"%@", [NSThread currentThread]);
}
- 自定義NSOperation
自定義NSOperation的步驟:
自定義一個(gè)繼承自NSOperation的子類,并重寫(xiě)- (void)main方法,在里面實(shí)現(xiàn)想執(zhí)行的任務(wù).
只要將任務(wù)添加到隊(duì)列中, 那么隊(duì)列在執(zhí)行自定義任務(wù)的時(shí)候,就會(huì)自動(dòng)調(diào)用main方法
//1.創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.創(chuàng)建任務(wù)
//自定義任務(wù)的好處: 提高代碼的復(fù)用性
YFYOperation *op1 = [[YFYOperation alloc] init];
YFYOperation *op2 = [[YFYOperation alloc] init];
//3.添加任務(wù)到隊(duì)列
[queue addOperation:op1];
[queue addOperation:op2];
- 重寫(xiě)
- (void)main方法的注意點(diǎn):
自己創(chuàng)建自動(dòng)釋放池(因?yàn)槿绻钱惒讲僮?,無(wú)法訪問(wèn)主線程的自動(dòng)釋 放池)
經(jīng)常通過(guò)- (BOOL)isCancelled方法檢測(cè)操作是否被取消,對(duì)取消做出響應(yīng)
NSOperationQueue
- NSOperationQueue的作用
NSOperation可以調(diào)用start方法來(lái)執(zhí)行任務(wù),但默認(rèn)是同步執(zhí)行的,如果將NSOperation添加到NSOperationQueue(操作隊(duì)列)中,系統(tǒng)會(huì)自動(dòng)異步執(zhí)行NSOperation中的操作 - NSOperationQueue與NSBlockOperation
//1.創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.創(chuàng)建任務(wù)
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1 == %@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2 == %@", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"3 == %@", [NSThread currentThread]);
}];
/*如果是使用block來(lái)封裝任務(wù), 那么有一種更簡(jiǎn)便的方法,只要利用隊(duì)列調(diào)用addOperationWithBlock:方法, 系統(tǒng)內(nèi)部會(huì)自動(dòng)封裝成一個(gè)NSBlockOperation,然后再添加到隊(duì)列中*/
// 3.添加任務(wù)到隊(duì)列
[queue addOperation:op1];
[queue addOperation:op2];
- NSOperationQueue與 NSInvocationOperation
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//2.創(chuàng)建任務(wù)
//只要是自己創(chuàng)建的隊(duì)列, 就會(huì)在子線程中執(zhí)行,而且默認(rèn)就是并發(fā)執(zhí)行
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download1) object:nil];
NSInvocationOperation *op2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download2) object:nil];
//3.添加任務(wù)到隊(duì)列中,只要將任務(wù)添加到隊(duì)列中, 隊(duì)列會(huì)自動(dòng)調(diào)用start
[queue addOperation:op1];
[queue addOperation:op2];
- (void)download1
{
NSLog(@"1 == %@", [NSThread currentThread]);
}
- (void)download2
{
NSLog(@"2 == %@", [NSThread currentThread]);
}
最大并發(fā)數(shù)
什么是并發(fā)數(shù)?
同時(shí)執(zhí)行的任務(wù)數(shù),比如,同時(shí)開(kāi)3個(gè)線程執(zhí)行3個(gè)任務(wù),并發(fā)數(shù)就是3最大并發(fā)數(shù)的相關(guān)方法:
- (NSInteger)maxConcurrentOperationCount;
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;自己創(chuàng)建的隊(duì)列默認(rèn)是并發(fā), 如果設(shè)置
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 1;//就是串行注意: 不能設(shè)置為0, 如果設(shè)置為0就不執(zhí)行任務(wù),
默認(rèn)情況下maxConcurrentOperationCount = -1
在開(kāi)發(fā)中并發(fā)數(shù)最多盡量不要超過(guò)5~6條
隊(duì)列的取消、暫停、恢復(fù)
- 只要設(shè)置隊(duì)列的suspended為YES, 那么就會(huì)暫停隊(duì)列中其它任務(wù)的執(zhí)行
self.queue.suspended = YES;
也就是說(shuō)不會(huì)再繼續(xù)執(zhí)行沒(méi)有執(zhí)行到得任務(wù) - 注意: 設(shè)置為暫停之后, 不會(huì)立即暫停,會(huì)繼續(xù)執(zhí)行當(dāng)前正在執(zhí)行的任務(wù), 直到當(dāng)前任務(wù)執(zhí)行完畢, 就不會(huì)執(zhí)行下一個(gè)任務(wù)了,也就是說(shuō), 暫停其實(shí)是暫停下一個(gè)任務(wù), 而不能暫停當(dāng)前任務(wù)
- 注意: 暫停是可以恢復(fù)的,只要設(shè)置隊(duì)列的suspended為NO, 那么就會(huì)恢復(fù)隊(duì)列中其它任務(wù)的執(zhí)行
- 取消隊(duì)列中所有的任務(wù)的執(zhí)行
[self.queue cancelAllOperations];
取消和暫停一樣, 是取消后面的任務(wù), 不能取消當(dāng)前正在執(zhí)行的任務(wù) - 注意: 取消是不可以恢復(fù)的
操作依賴
- NSOperation之間可以設(shè)置依賴來(lái)保證執(zhí)行順序,比如一定要讓操作A執(zhí)行完后,才能執(zhí)行操作B,可以這么寫(xiě)
[operationB addDependency:operationA];// 操作B依賴于操作A - 注意:不能相互依賴,比如A依賴B,B依賴A.
- 可以在不同queue的NSOperation之間創(chuàng)建依賴關(guān)系
// 1.創(chuàng)建隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSOperationQueue *queue2 = [[NSOperationQueue alloc] init];
// 2.創(chuàng)建任務(wù)
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1-------%@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2-------%@", [NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"3-------%@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"4-------%@", [NSThread currentThread]);
for (int i = 0; i < 1000; i++) {
NSLog(@"%i", i);
}
}];
NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"5-------%@", [NSThread currentThread]);
}];
// 3.添加依賴
[op5 addDependency:op1];
[op5 addDependency:op2];
[op5 addDependency:op3];
[op5 addDependency:op4];
// 4.監(jiān)聽(tīng)op4什么時(shí)候執(zhí)行完畢
op4.completionBlock = ^{
NSLog(@"op4中所有的操作都執(zhí)行完畢了");
};
// 5.添加任務(wù)到隊(duì)列
[queue addOperation:op1];
[queue addOperation:op2];
[queue2 addOperation:op3];
[queue2 addOperation:op4];
[queue addOperation:op5];