一咏窿、
NSOperation是基于GCD之上的更高一層封裝息拜,NSOperation需要配合NSOperationQueue來實現(xiàn)多線程廉丽。
NSOperation實現(xiàn)多線程的步驟如下:
1、創(chuàng)建任務(wù):先將需要執(zhí)行的操作封裝到NSOperation對象中弄兜。
2药蜻、創(chuàng)建隊列:創(chuàng)建NSOperationQueue。
3替饿、將任務(wù)加入到隊列中:將NSOperation對象添加到NSOperationQueue中语泽。
需要注意的是,NSOperation是個抽象類视卢,實際運用中需要使用它的子類踱卵,有三種方式:
1、使用子類NSInvocationOperation
2据过、使用子類NSBlockOperation
3惋砂、定義繼承NSOreration的子類蔬充,通過實現(xiàn)內(nèi)部相應(yīng)的方法來封裝任務(wù)。
NSOperation的三種創(chuàng)建方式
1班利、NSInvocationOperation的使用
創(chuàng)建NSInvocationOperation對象并關(guān)聯(lián)方法,之后start榨呆。
-(void)testNSInvocationOperation {
//創(chuàng)建NSInvocationOperaion
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationOperation) object:nil];
[invocationOperation start];
}
-(void)invocationOperation {
NSLog(@"NSInvocationOperation包含的任務(wù)罗标,沒有加入隊列=======%@",[NSThread currentThread]);
}
結(jié)論:程序在主線程執(zhí)行,沒有開啟新線程积蜻。
這是因為NSOperation多線程的使用需要配合隊列NSOperationQueue來實現(xiàn)多線程
二闯割、NSBlockOperation的使用
把任務(wù)放到NSBlockOperation的block中,然后start竿拆。
-(void)testNSBlockOperation {
//把任務(wù)放到block中
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"NSBlockOperation包含的任務(wù)宙拉,沒有加入隊列=====%@",[NSThread currentThread]);
}];
[blockOperation start];
}
得出結(jié)論:主線程執(zhí)行,沒有開啟新線程丙笋。
同樣的谢澈,NSBlockOperation可以配合隊列NSOperationQueue來實現(xiàn)多線程。
但是NSBlockOperation有一個方法addExecutionBlock:御板,通過這個方法可以讓NSBlockOperation實現(xiàn)多線程锥忿。
-(void)testNSBLockOperationExecution {
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBLock:^{
NSLog(@"NSBlockOperation運用addExecutionBlock主任務(wù)========%@", [NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"NSBlockOperation運用addExecutionBlock方法添加任務(wù)1========%@", [NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"NSBlockOperation運用addExecutionBlock方法添加任務(wù)2========%@", [NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"NSBlockOperation運用addExecutionBlock方法添加任務(wù)3========%@", [NSThread currentThread]);
}];
[blockOperation start];
}
可以看出,NSBlockOperation創(chuàng)建時block中的任務(wù)是在主線程執(zhí)行怠肋,而運用addExecutionBlock加入的任務(wù)是在子線程執(zhí)行的敬鬓。
3、運用繼承自NSOperation的子類(略過)
三笙各、隊列NSOperationQueue
NSOperationQueue只有兩種隊列:主隊列钉答、其他隊列。其他隊列包含了串行和并發(fā)杈抢。
主隊列的創(chuàng)建如下数尿,主隊列上的任務(wù)是在主線程執(zhí)行的。
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
注意:
1惶楼、非主隊列(其他隊列)可以實現(xiàn)串行或并行砌创。
2、隊列NSOperationQueue有一個參數(shù)中做最大并發(fā)數(shù):maxConcurrentOperationCount鲫懒。
3嫩实、maxConcurrentOperatoinCount默認(rèn)為-1,直接并發(fā)執(zhí)行窥岩,所以加入到'非隊列'中的任務(wù)默認(rèn)就是并發(fā)甲献,開啟多線程。
4颂翼、當(dāng)maxConcurrentOperationCount為1時晃洒,則表示不開線程慨灭,也就是串行。
5球及、當(dāng)maxConcurrentOperationCount大于1時氧骤,進(jìn)行并發(fā)執(zhí)行。
6吃引、系統(tǒng)對最大并發(fā)數(shù)有一個限制筹陵,所以即使程序員把maxconcurrentOperationiCount設(shè)置的很大,系統(tǒng)也會自動調(diào)整镊尺。所以把最大并發(fā)數(shù)設(shè)置的很大是沒有意義的朦佩。
四、NSOperation+NSOperationQueue
把任務(wù)加入隊列庐氮,這才是NSOperation的常規(guī)使用方式语稠。
1、addOperation添加任務(wù)到隊列
先創(chuàng)建好任務(wù)弄砍,然后運用-(void)addOperation:(NSOpreation*)op方法來把任務(wù)添加到隊列中仙畦,示例代碼如下:
- (void)testOperationQueue {
// 創(chuàng)建隊列,默認(rèn)并發(fā)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 創(chuàng)建操作音婶,NSInvocationOperation
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationOperationAddOperation) object:nil];
// 創(chuàng)建操作议泵,NSBlockOperation
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
NSLog(@"addOperation把任務(wù)添加到隊列======%@", [NSThread currentThread]);
}
}];
[queue addOperation:invocationOperation];
[queue addOperation:blockOperation];
}
- (void)invocationOperationAddOperation {
NSLog(@"invocationOperation===aaddOperation把任務(wù)添加到隊列====%@", [NSThread currentThread]);
}
2、addOperationWithBlock添加任務(wù)到隊列
這是一個更方便的把任務(wù)添加到隊列的方法桃熄,直接把任務(wù)寫在block中先口,添加到任務(wù)中。
- (void)testAddOperationWithBlock {
// 創(chuàng)建隊列瞳收,默認(rèn)并發(fā)
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 添加操作到隊列
[queue addOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
NSLog(@"addOperationWithBlock把任務(wù)添加到隊列======%@", [NSThread currentThread]);
}
}];
}
五碉京、NSOperation的其他操作
1、取消隊列NSOperationQueue的所有操作螟深,NSOperationQueue對象方法----cancelAllOperations
2谐宙、取消NSOperation的某個操作,NSOperation對象方法------cancel
3界弧、使隊列暫头豺撸或繼續(xù)------[queue setSuspended:YES];
4、判斷隊列是否暫停------isSuspended
六垢箕、NSOperation的操作依賴
NSOperation有一個非常好用的方法划栓,就是操作依賴√趸瘢可以從字面意思理解:某一個操作(operation2)依賴于另一個操作(operation1)忠荞,只有當(dāng)operation1執(zhí)行完畢,才能執(zhí)行operation2,這時委煤,就是操作依賴大顯身手的時候了堂油。
- (void)testAddDependency {
// 并發(fā)隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 操作1
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 3; i++) {
NSLog(@"operation1======%@", [NSThread currentThread]);
}
}];
// 操作2
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"****operation2依賴于operation1,只有當(dāng)operation1執(zhí)行完畢碧绞,operation2才會執(zhí)行****");
for (int i = 0; i < 3; i++) {
NSLog(@"operation2======%@", [NSThread currentThread]);
}
}];
// 使操作2依賴于操作1
[operation2 addDependency:operation1];
// 把操作加入隊列
[queue addOperation:operation1];
[queue addOperation:operation2];
}