iOS多線程編程之NSOperation

資料來源 NShipster之NSOperation

對于異步執(zhí)行技術(shù)GCD的API已經(jīng)非常簡單高效,但對于某些task之間存在依賴或是監(jiān)測task的執(zhí)行狀態(tài)等需求GCD就顯得不那么高效;因此cocoa框架中就提供了一個使用面向?qū)ο笏枷雭斫鉀Q異步操作的NSOperation,同時結(jié)合NSOperationQueue會使得異步操作更加簡單高效;

NSOperation

NSOperation是一個抽象基類,只能實例化子類才能使用;開發(fā)框架中已經(jīng)存在了兩個實例NSBlockOperation和NSInvocationOperation

NSBlockOperation

NSBlockOperation實例化操作可以在block中執(zhí)行task,并且當(dāng)task只有一個的時候task在主線程中執(zhí)行,當(dāng)task增加時會另外創(chuàng)建線程執(zhí)行task;

NSBlockOperation 在調(diào)用start方法時所有添加的task會hold住主線程,也就是所有的task執(zhí)行完畢后才繼續(xù)執(zhí)行主線程的其他操作

NSBlockOperation 中添加多個task時,各個task的執(zhí)行順序不一定,但是第添加的task一定會在主線程中被執(zhí)行

NSBlockOperation* blockOperation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"blockOp1:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
    NSLog(@"blockOp2:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
    NSLog(@"blockOp3:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
    [NSThread sleepForTimeInterval:3.0f];
    NSLog(@"blockOp4:%@",[NSThread currentThread]);
}];
blockOperation.completionBlock = ^{
    NSLog(@"blockOperation over!");
};
[blockOperation start];
NSLog(@"run over!!!:%@",[NSThread currentThread]);
/*
  HZFoundation[46406:1977543] blockOp3:<NSThread: 0x100700110>{number = 2, name = (null)}
  HZFoundation[46406:1977541] blockOp2:<NSThread: 0x1001037c0>{number = 3, name = (null)}
  HZFoundation[46406:1977517] blockOp1:<NSThread: 0x100502e50>{number = 1, name = main}
  HZFoundation[46406:1977542] blockOp4:<NSThread: 0x100700150>{number = 4, name = (null)}
  HZFoundation[46406:1977517] run over!!!:<NSThread: 0x100502e50>{number = 1, name = main}
 */

根據(jù)上述log的輸出可用GCD模擬一下NSBlockOperation內(nèi)部實現(xiàn)

  -(void)implementationBlockOperation{
// 添加task
OperationBlock block1=^{
    NSLog(@"block1%@",[NSThread currentThread]);
};
OperationBlock block2=^{
    NSLog(@"block2%@",[NSThread currentThread]);
};
OperationBlock block3=^{
    NSLog(@"block3%@",[NSThread currentThread]);
};
OperationBlock block4=^{
    NSLog(@"block4%@",[NSThread currentThread]);
};
OperationBlock block5=^{
    [NSThread sleepForTimeInterval:3.0f];
    NSLog(@"block5%@",[NSThread currentThread]);
};
// 所有執(zhí)行task的集合
NSArray* operationBlcoks = [NSArray arrayWithObjects:block1,block2,block3,block4,block5,nil];
//根據(jù)上面打印的block執(zhí)行線程名稱可以看到,線程名稱各不相同,由此推測block的執(zhí)行在一個并發(fā)隊列中
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.*.implementationBlockOperation", DISPATCH_QUEUE_CONCURRENT);
//打印的內(nèi)容可以看到NSOperation是block住主線程的,也就是所有的任務(wù)執(zhí)行完畢后才繼續(xù)執(zhí)行task,能夠執(zhí)行此操作的dispatch_group最合適
dispatch_group_t dispatchGroup = dispatch_group_create();
for (NSInteger index=0; index<operationBlcoks.count; index++) {
    // 此處的狀態(tài)判斷是由于打印線程名稱看到每次第一個任務(wù)的執(zhí)行線程總是在主線程中完成的
    if (index==0) {
        // 此處處理和原設(shè)計相違背,雖然是在主線程中執(zhí)行但是執(zhí)行的順序每次都是最先添加的被執(zhí)行
        OperationBlock block = operationBlcoks[0];
        block();
    }else{
        dispatch_group_async(dispatchGroup, concurrentQueue, ^{
            OperationBlock block = operationBlcoks[index];
            block();
        });
    }
}
dispatch_group_wait(dispatchGroup, DISPATCH_TIME_FOREVER);
NSLog(@"implementationBlockOperation over!%@",[NSThread currentThread]);
}    

上述實現(xiàn)代碼唯一的不足時第一task執(zhí)行順序會影響其他task,因為它總是第一個被執(zhí)行,目前還沒有考慮出合適的實現(xiàn)方法;

NSInvocationOperation

NSInvocationOperation的使用和UIControl的使用模式很相似

-(void)operationInvocation{
   NSInvocationOperation* operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction) object:nil];
[operation1 start];
}

-(void)operationAction{
    NSLog(@"%@--->",[NSThread currentThread]);
}

NSOperationQueue

  // 創(chuàng)建operation
NSBlockOperation* blockOperation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"blockOp1:%@",[NSThread currentThread]);
}];
NSBlockOperation* blockOperation1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"blockOp2:%@",[NSThread currentThread]);
}];
// 創(chuàng)建operationQueue
NSOperationQueue* operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperation:blockOperation];
[operationQueue addOperation:blockOperation1];  
[operationQueue setMaxConcurrentOperationCount:4]; // 設(shè)置task最大執(zhí)行并發(fā)數(shù)
[blockOperation addDependency:blockOperation1];// operation之間添加依賴關(guān)系
[operationQueue waitUntilAllOperationsAreFinished];// 等待所有的operation執(zhí)行完畢后
[operationQueue cancelAllOperations];//取消所有operation操作
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容