文章分享至我的個人技術部落格: https://cainluo.github.io/15019481375874.html
之前, 我們花了小段時間就把GCD
給摸了個底, 知道了GCD
的操作, 不知道大家有沒有好好去耍耍, 這次我們再來講講, iOS
中的多執行緒操作.
NSOperation
, NSOperation
它是基於GCD
的基礎進行封裝的, 雖然GCD
簡單, 但是是C
風格程式碼, 而NSOperation
的話, 它是Objective-C
風格的程式碼, 看起來更加的iOS
一些, 程式碼讀起來也是比較更加的直觀, 讓我們一起去溜溜看吧~
轉載宣告:如需要轉載該文章, 請聯絡作者, 並且註明出處, 以及不能擅自修改本文.
NSOperation簡介
剛剛我們提到了NSOperation
是蘋果爸爸基於GCD
的封裝, 程式碼風格是Objective-C
, 所以更加簡單易懂, 可讀性也高.
但這裡需要注意一下, NSOperation
是需要和NSOperationQueue
配合著來使用的, 這是為啥呢?
因為NSOperation
單獨使用的話, 它是屬於同步操作, 並不具有開啟新執行緒的功能, 只有配合著NSOperationQueue
才能夠實現多執行緒的操作.
我們都知道NSOperation
是基於GCD
來封裝了, 那麼使用起來也是和GCD
差不多, 其中的NSOperation
就相當於GCD
中的任務, 而NSOperationQueue
就相當於GCD
中的佇列啦.
那麼使用NSOperation
需要三個步驟:
- 建立任務: 這裡我們需要把執行的任務丟到
NSOperation
裡 - 建立佇列: 建立
NSOperationQueue
佇列物件 - 新增任務到佇列中: 最後將
NSOperation
物件新增到NSOperationQueue
中, 這樣就完成了.
在使用的時候, 系統就會自動將NSOperationQueue
中的NSOperation
取出, 然後就在新執行緒裡完成操作.
NSOperation和NSOperationQueue的基本使用
在開始擼程式碼之前, 我們還得知道一件事, NSOperation
它是屬於一個抽象類, 並不能用來封裝任務, 那咋辦呢?
沒關係NSOperation
這裡提供三種方法來實現:
- 使用
NSInvocationOperation
子類來封裝任務 - 使用
NSBlockOperation
子類來封裝任務 - 使用繼承於
NSOperation
的子類來封裝任務, 也就是說, 你可以自己寫一個自定義的子類來實現封裝任務
剛剛我們也知道了, 單獨使用NSOperation
的時候是屬於同步執行, 所以下面我們會了解三種建立的方式.
NSInvocationOperation
程式碼擼起:
- (void)invocationOperation {
NSInvocationOperation *invocationPeration = [[NSInvocationOperation alloc] initWithTarget:self
selector:@selector(runTheOperation)
object:nil];
[invocationPeration start];
}
- (void)runTheOperation {
NSLog(@"執行任務, 當前的執行緒為: %@", [NSThread currentThread]);
}
複製程式碼
2017-08-06 00:23:58.611 NSOperation-Example[961:42623] 執行任務, 當前的執行緒為: <NSThread: 0x608000066a00>{number = 1, name = main}
複製程式碼
在結果裡, 我們可以看到在沒有使用NSOperationQueue
的時候, 是在主執行緒中執行, 並沒有開啟新執行緒.
NSBlockOperation
- (void)blockOperation {
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"執行任務, 當前的執行緒為: %@", [NSThread currentThread]);
}];
[blockOperation start];
}
複製程式碼
2017-08-06 00:26:54.808 NSOperation-Example[1002:47303] 執行任務, 當前的執行緒為: <NSThread: 0x60800006c340>{number = 1, name = main}
複製程式碼
在結果中, 我們看到使用NSBlockOperation
也是在主執行緒中執行任務, 並沒有開啟新執行緒.
但是在NSBlockOperation
中, 我們還看到了另外一個方法, 這個方法是用來幹嘛的呢? 來看看程式碼吧:
- (void)blockOperation {
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"執行任務, 當前的執行緒為: %@", [NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"執行第二個任務, 當前的執行緒為: %@", [NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"執行第三個任務, 當前的執行緒為: %@", [NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"執行第四個任務, 當前的執行緒為: %@", [NSThread currentThread]);
}];
[blockOperation start];
}
複製程式碼
2017-08-06 00:30:10.238 NSOperation-Example[1043:51425] 執行任務, 當前的執行緒為: <NSThread: 0x60000007bac0>{number = 1, name = main}
2017-08-06 00:30:10.238 NSOperation-Example[1043:51592] 執行第四個任務, 當前的執行緒為: <NSThread: 0x608000267380>{number = 4, name = (null)}
2017-08-06 00:30:10.238 NSOperation-Example[1043:51609] 執行第二個任務, 當前的執行緒為: <NSThread: 0x600000266c40>{number = 3, name = (null)}
2017-08-06 00:30:10.238 NSOperation-Example[1043:51594] 執行第三個任務, 當前的執行緒為: <NSThread: 0x608000267200>{number = 5, name = (null)}
複製程式碼
從列印的結果, 我們可以看出, 這個方法是可以新增額外的任務, 並且在子執行緒同步執行.
自定義NSOperation子類
這裡, 我們建立一個繼承於NSOperation
的子類, 暫時想不到有什麼好的場景, 這裡我們簡單寫寫就好了.
首先我們建立一個繼承於NSOperation
的子類, 並重寫了- (void)main;
方法:
#import "CLOperation.h"
@implementation CLOperation
- (void)main {
for (NSInteger i = 0; i < 5; i++) {
NSLog(@"執行了第%zd次任務, 當前執行緒為: %@", i, [NSThread currentThread]);
}
}
@end
複製程式碼
然後回到Controller
, 執行一番:
- (void)customOperation {
CLOperation *clOperation = [[CLOperation alloc] init];
[clOperation start];
}
複製程式碼
2017-08-06 00:37:32.223 NSOperation-Example[1123:59243] 執行了第0次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
2017-08-06 00:37:32.223 NSOperation-Example[1123:59243] 執行了第1次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
2017-08-06 00:37:32.224 NSOperation-Example[1123:59243] 執行了第2次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
2017-08-06 00:37:32.224 NSOperation-Example[1123:59243] 執行了第3次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
2017-08-06 00:37:32.224 NSOperation-Example[1123:59243] 執行了第4次任務, 當前執行緒為: <NSThread: 0x60000006c500>{number = 1, name = main}
複製程式碼
看到輸出的結果, 也是在意料之內, 也是在主執行緒中執行, 並沒有開啟新執行緒.
總結
這一章, 我們就簡單的介紹一下NSOperation
, 並且熟悉一下基本的操作, 回頭我們再把NSOperation
和NSOperationQueue
的配合使用補全.
工程地址
專案地址: https://github.com/CainRun/iOS-Project-Example/tree/master/NSOperation-Example