NSOperation簡單使用

NSOperation實現(xiàn)多線程編程,實現(xiàn)步驟大致是這樣的:

  1. 先將需要執(zhí)行的操作封裝到一個NSOperation對象中
  2. 然后將NSOperation對象添加到NSOperationQueue中
  3. 系統(tǒng)會自動將NSOperation中封裝的操作放到一條新線程中執(zhí)行

但是NSOperation本身是一個抽象類,要使用可以通過以下幾個辦法:

  1. 使用NSInvocationOperation
  2. 使用NSBlockOperation
  3. 自定義NSOperation的子類

簡單的使用方法

NSInvocationOperation簡單用法:

//創(chuàng)建操作
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector: @selector(download) object:nil];
//執(zhí)行封裝好的操作
[operation start];

-(void)download
{
NSLog(@"download----線程號:%@", [NSThreadcurrentThread]);
}

NSBlockOperation簡單用法:

NSBlockOperation*operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作1線程號:%@", [NSThread currentThread]);
}];
[operation1 start];

根據(jù)打印的結(jié)果我們會發(fā)現(xiàn),直接調(diào)用start方法時,系統(tǒng)并不會開辟一個新的線程去執(zhí)行任務(wù),任務(wù)會在當(dāng)前線程同步執(zhí)行.

注意: 這里我們說的是當(dāng)前線程而非主線程,意即:如果是在主線程中調(diào)用operation的start方法,那么該任務(wù)是在主線程中執(zhí)行;但如果是在其他子線程調(diào)用start方法,任務(wù)則是在其他子線程執(zhí)行.顯然調(diào)用start方法執(zhí)行操作不是我們開線程的初衷。

NSOperationQueue使用

NSOperation與NSOperationQueue進(jìn)行結(jié)合,才會發(fā)揮出這種多線程技術(shù)的最大功效.當(dāng)NSOperation被添加到NSOperationQueue中后,就會全自動地執(zhí)行異步操作.

//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//創(chuàng)建操作
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download) object:nil];
//將操作加入隊列
[queue addOperation: operation];

- (void)download
{
  NSLog(@"download----線程號:%@", [NSThread currentThread]);
}

將操作放入隊列中,會自動異步執(zhí)行。
打印信息如下:
download----****線程號:****{number = 2, name = (null)}
我們創(chuàng)建線程就是為了異步執(zhí)行代碼,所以經(jīng)常使用的就是將操作加入隊列中

使用block 創(chuàng)建

//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//創(chuàng)建操作
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
  NSLog(@"這里是線程操作線程號:%@", [NSThread currentThread]);
}];
//將操作加入隊列
[queue addOperation: operation];

打印信息如下:
**這里是線程操作******線程號:****{number = 2, name = (null)}****
從線程號可以看出該線程操作不是在當(dāng)前線程中運行的

創(chuàng)建多個操作來加入隊列

//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//創(chuàng)建操作
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作1線程號:%@", [NSThread currentThread]);
}];
NSBlockOperation*operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作2線程號:%@", [NSThread currentThread]);
}];
NSBlockOperation*operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作3線程號:%@", [NSThread currentThread]);
}];
//將操作加入隊列
[queue addOperation: operation1];
[queue addOperation: operation2];
[queue addOperation: operation3];

打印信息如下:
2016-02-17 17:34:03.282 tttt[2559:204434]****這里是線程操作****3****線程號:****{number = 4, name = (null)}
2016-02-17 17:34:03.282 tttt[2559:204432]****這里是線程操作****1****線程號:****{number = 3, name = (null)}
2016-02-17 17:34:03.282 tttt[2559:204433]****這里是線程操作****2****線程號:****{number = 2, name = (null)}
從線程號可以看出該線程操作不是在當(dāng)前線程中運行的

在一個操作中添加多個子任務(wù)

//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//創(chuàng)建操作
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作1線程號:%@", [NSThread currentThread]);
}];
[operation1 addExecutionBlock:^{
NSLog(@"這里是線程操作1的分支線程號:%@", [NSThread currentThread]);
}];
//將操作加入隊列
[queue addOperation: operation1];

打印信息如下:
2016-02-17 17:37:28.037 tttt[2572:207727]****這里是線程操作****1****線程號:****{number = 2, name = (null)}
**2016-02-17 17:37:28.037 tttt[2572:207728]****這里是線程操作****1****的分支******線程號:****{number = 3, name = (null)}****

可以看到,自動分成了兩個線程來操作,且第二個線程一定是在第一個線程執(zhí)行完畢才開始執(zhí)行

----------------
但是這種增加任務(wù)的方法和上面那種還是有區(qū)別
代碼如下:

//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//創(chuàng)建操作
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作1線程號:%@", [NSThread currentThread]);
}];
[operation1 addExecutionBlock:^{
NSLog(@"這里是線程操作1的分支線程號:%@", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作2線程號:%@", [NSThread currentThread]);
}];
//將操作加入隊列
[queue addOperation: operation1];
[queue addOperation: operation2];

創(chuàng)建兩個操作來加入隊列中,其中線程操作1有一個分支任務(wù)
打印結(jié)果如下:
2016-02-17 17:41:35.210 tttt[2587:211052]****這里是線程操作****2****線程號:****{number = 2, name = (null)}
2016-02-17 17:41:35.210 tttt[2587:211051]****這里是線程操作****1****線程號:****{number = 3, name = (null)}
**2016-02-17 17:41:35.210 tttt[2587:211055]****這里是線程操作****1****的分支******線程號:****{number = 4, name = (null)}****

可以看到,線程操作1和線程操作2先執(zhí)行,操作1的分支任務(wù)最后執(zhí)行。有一個明顯的先后關(guān)系。

使用隊列添加線程操作

//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//創(chuàng)建操作
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作1線程號:%@", [NSThread currentThread]);
}];
[operation1 addExecutionBlock:^{
NSLog(@"這里是線程操作1的分支線程號:%@", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作2線程號:%@", [NSThread currentThread]);
}];
//將操作加入隊列
[queue addOperation: operation1];
[queue addOperation: operation2];
[queue addOperationWithBlock:^{
NSLog(@"這里是線程操作3線程號:%@", [NSThread currentThread]);
}];

直接使用隊列對象來添加線程操作。

打印信息如下:
2016-02-17 18:01:25.354 tttt[2615:221510]****這里是線程操作****3****線程號:****{number = 3, name = (null)}
2016-02-17 18:01:25.354 tttt[2615:221506]****這里是線程操作****2****線程號:****{number = 2, name = (null)}
2016-02-17 18:01:25.354 tttt[2615:221504]****這里是線程操作****1****線程號:****{number = 4, name = (null)}
**2016-02-17 18:01:25.354 tttt[2615:221514]****這里是線程操作****1****的分支******線程號:****{number = 5, name = (null)}****

線程3是通過隊列queue直接加入進(jìn)來的,但其效果和使用operation是一樣的

設(shè)置最大線程并發(fā)數(shù)

可以通過maxConcurrentOperationCount來設(shè)置最大線程并發(fā)數(shù)

//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//設(shè)置最大并發(fā)數(shù)
queue.maxConcurrentOperationCount=2;
//創(chuàng)建操作
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作1線程號:%@", [NSThread currentThread]);
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作2線程號:%@", [NSThread currentThread]);
}];
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作3線程號:%@", [NSThread currentThread]);
}];
NSBlockOperation *operation4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"這里是線程操作4線程號:%@", [NSThread currentThread]);
}];
//將操作加入隊列
[queue addOperation: operation1];
[queue addOperation: operation2];
[queue addOperation: operation3];
[queue addOperation: operation4];

打印信息如下:

2016-02-23 15:20:32.315 tttt[1443:161764] ****這里是線程操作****2 ****線程號:****<NSThread: 0x7fd019d30730>{number = 3, name = (null)}
2016-02-23 15:20:32.315 tttt[1443:161765] ****這里是線程操作****1 ****線程號:****<NSThread: 0x7fd019f0a290>{number = 2, name = (null)}
2016-02-23 15:20:32.316 tttt[1443:161766] ****這里是線程操作****3 ****線程號:****<NSThread: 0x7fd019ea8890>{number = 5, name = (null)}
2016-02-23 15:20:32.316 tttt[1443:161767] ****這里是線程操作****4 ****線程號:****<NSThread: 0x7fd019d00e10>{number = 4, name = (null)}

根據(jù)線程開啟時間可以看出,同一時間只有兩個線程開啟

本篇先講到這里,下一篇說一說自定義NSOperation的子類

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容