在前面介紹了
NSThread的使用 贸辈,
GCD的使用释树,
接下來我們將介紹NSOperation的使用
簡介
在iOS的多線程開發(fā)過程中,不可避免的要使用多線程擎淤,多線程可以在不阻塞主線程的前提下提高效率奢啥。在這里呢,我們將看看多線程中NSOperation是如何使用的嘴拢。
NSInvocationOperation
The NSInvocationOperation
class is a concrete subclass of NSOperation that you use to initiate an operation that consists of invoking a selector on a specified object. This class implements a non-concurrent operation.
根據(jù)蘋果官方的解釋說桩盲,NSInvocationOperation
是NSOperation
的一個子類,你可以初始化一個操作席吴,該操作在一個指定的對象上去調(diào)用一個selector赌结,并且NSOperation
這個類實(shí)現(xiàn)了一個非并發(fā)的操作。具體怎么使用NSInvocationOperation
這個類呢孝冒?
NSInvocationOperation的創(chuàng)建
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationTest) object:nil];
NSInvocationOperation創(chuàng)建完成之后柬姚,怎么觸發(fā)該線程的執(zhí)行?一共有兩種方式執(zhí)行該線程
方式一:
//調(diào)用start方法執(zhí)行庄涡,此執(zhí)行方式在主線程中執(zhí)行量承,沒有開辟新的線程
// ThreadDemo[20397:12090175] ------------<NSThread: 0x60400007da00>{number = 1, name = main}-----
[operation start];
調(diào)用start方法執(zhí)行此線程,但是使用此方法穴店,并不會開辟新的線程來執(zhí)行代碼
方式二:
//加入到隊(duì)列中去執(zhí)行撕捍,此種方式會開辟線程,在新的線程中執(zhí)行代碼
// ThreadDemo[20432:12091400] ------------<NSThread: 0x600000273240>{number = 3, name = (null)}-----
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
根據(jù)打印信息可以看出泣洞,把創(chuàng)建的NSInvocationOperation加入到一個queue隊(duì)列中去執(zhí)行忧风,會開辟新的線程執(zhí)行任務(wù)。
NSBlockOperation
The NSBlockOperation
class is a concrete subclass of NSOperationthat manages the concurrent execution of one or more blocks. You can use this object to execute several blocks at once without having to create separate operation objects for each. When executing more than one block, the operation itself is considered finished only when all blocks have finished executing.
NSBlockOperation
類是NSOperation
的一個具體子類球凰,它管理一個或多個塊的并發(fā)執(zhí)行阀蒂。您可以使用這個對象一次執(zhí)行幾個塊,而不必為每個塊創(chuàng)建單獨(dú)的操作對象弟蚀。當(dāng)執(zhí)行多個塊時蚤霞,只有當(dāng)所有塊都完成執(zhí)行時,才考慮操作本身义钉。
NSBlockOperation的創(chuàng)建
//創(chuàng)建NSBlockOperation線程方式1
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation------%@-----", [NSThread currentThread]);
}];
[operation start];
//創(chuàng)建NSBlockOperation線程方式2
NSBlockOperation *operation1 = [[NSBlockOperation alloc] init];
[operation1 addExecutionBlock:^{
NSLog(@"------operation1------%@-----", [NSThread currentThread]);
}];
[operation1 start];
這樣創(chuàng)建后調(diào)用start方法昧绣,同樣在主線程中執(zhí)行,下面看看把NSBlockOperation添加到queue隊(duì)列中去執(zhí)行
NSBlockOperation *operation = [[NSBlockOperation alloc] init];
[operation addExecutionBlock:^{
NSLog(@"------block1------%@-----", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"------block2------%@-----", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"------block3------%@-----", [NSThread currentThread]);
}];
[operation addExecutionBlock:^{
NSLog(@"------block4------%@-----", [NSThread currentThread]);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
可以看出捶闸,加入到queue隊(duì)列中的任務(wù)全都是異步執(zhí)行
使用NSOperationQueue來創(chuàng)建任務(wù)
/**
使用queue隊(duì)列來自己添加任務(wù)并執(zhí)行
*/
- (void)testOperationQueue {
//創(chuàng)建queue隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//添加任務(wù)
[queue addOperationWithBlock:^{
NSLog(@"------block1------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block2------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block3------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block4------%@-----", [NSThread currentThread]);
}];
}
可以看出夜畴,使用queue隊(duì)列來創(chuàng)建任務(wù)拖刃,省去了創(chuàng)建NSInvocationOperation
和NSBlockOperation
再加入到隊(duì)列中執(zhí)行。
上面列出了三種實(shí)現(xiàn)NSOperation
創(chuàng)建多線程的方式贪绘,在具體的工作中兑牡,使用哪種方式還是要根據(jù)工作需要具體對待。
隊(duì)列的使用----依賴執(zhí)行任務(wù)
有這個一個場景:任務(wù)3的執(zhí)行依賴于任務(wù)2税灌,任務(wù)2的執(zhí)行依賴于任務(wù)1均函,相當(dāng)于一個串行隊(duì)列,只有當(dāng)前面一個執(zhí)行完成之后才開始下一個任務(wù)的執(zhí)行菱涤,下面看看具體的實(shí)現(xiàn)方式:
/**
使用場景一:任務(wù)的依賴執(zhí)行
*/
- (void)testDepenceyOperation {
//創(chuàng)建要執(zhí)行的任務(wù)
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation1------%@-----", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation2------%@-----", [NSThread currentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"------operation3------%@-----", [NSThread currentThread]);
}];
//給任務(wù)添加依賴苞也,任務(wù)3依賴任務(wù)2,任務(wù)2依賴任務(wù)1
[operation3 addDependency:operation2];
[operation2 addDependency:operation1];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
}
隊(duì)列的使用---設(shè)置最大并發(fā)數(shù)
設(shè)置最大并發(fā)數(shù)量粘秆,為了保證app的整個生命周期不會占用過多的資源如迟,在有大量并發(fā)線程執(zhí)行的時候,一定要進(jìn)行設(shè)置攻走,不然可能會造成app閃退殷勘。
- (void)testMacConcurrentOperationCount {
//創(chuàng)建queue隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//設(shè)置線程的最大并發(fā)數(shù)量
queue.maxConcurrentOperationCount = 3;
//添加任務(wù)
[queue addOperationWithBlock:^{
NSLog(@"------block1------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block2------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block3------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block4------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block5------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block6------%@-----", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"------block7------%@-----", [NSThread currentThread]);
}];
}
最后附上以上代碼鏈接
上述所有代碼均可以在NSOperationDemo中查看,有需要可以自行獲取