上一篇文章我們已經(jīng)了解過(guò)了什么是多線程,以及GCD的一些使用方法,下面繼續(xù)介紹另外一種iOS中實(shí)現(xiàn)多線程的方法NSOperation。
在學(xué)習(xí)這個(gè)類之前,我們還是需要知道幾個(gè)關(guān)鍵詞:
- 1.任務(wù) : 就是你的具體操作,比如你要上傳照片、讀寫(xiě)數(shù)據(jù)庫(kù)等等,都可以視為任務(wù)
- 2.隊(duì)列 : 隊(duì)列就是規(guī)定這個(gè)任務(wù)是怎么執(zhí)行的,是串行,還是并行
- 3.線程:這個(gè)之前已經(jīng)介紹過(guò)了,這里就不多多介紹,想了解的同學(xué)-->傳送門(mén):iOS多線程詳細(xì)說(shuō)明(GCD篇-就是個(gè)玩兒)
NSOperation
NSOperation 是個(gè)抽象類,并不具備封裝操作的能力,必須使?它的子類:NSInvocationOperation(任務(wù))、NSBlockOperation(任務(wù))、NSOperationQueue(隊(duì)列)
1.NSInvocationOperation(任務(wù))
NSInvocationOperation 的作用是創(chuàng)建一個(gè)任務(wù),我們來(lái)看一下具體的代碼
- (void)viewDidLoad {
[super viewDidLoad];
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationRun) object:nil];
[operation1 start];//?< 手動(dòng)開(kāi)始任務(wù)
}
- (void)operationRun
{
NSLog(@"我是第一個(gè)queue%@",[NSThread currentThread]); //?< 主線程
}
這里我們值得注意的是,當(dāng)這個(gè)任務(wù)沒(méi)有添加到隊(duì)列中時(shí),默認(rèn)時(shí)在當(dāng)前線程中 同步 執(zhí)行的,并且任務(wù)創(chuàng)建以后,并沒(méi)有立即執(zhí)行需要我們手動(dòng)開(kāi)啟
2. NSBlockOperation(任務(wù))
NSBlockOperation的作用跟NSInvocationOperation一樣,只不過(guò)NSBlockOperation創(chuàng)建任務(wù)的形式是以block的形式來(lái)創(chuàng)建的。
- (void)viewDidLoad {
[super viewDidLoad];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是block任務(wù) %@",[NSThread currentThread]);
}];
[operation2 start];//?< 手動(dòng)開(kāi)始任務(wù)
}
當(dāng)然NSBlockOperation的任務(wù),也是默認(rèn)在當(dāng)前的線程下同步 執(zhí)行,也需要我們來(lái)手動(dòng)開(kāi)啟
3.NSOperationQueue(隊(duì)列)
NSOperationQueue(隊(duì)列) 和GCD中的并發(fā)隊(duì)列、串行隊(duì)列略有不同的是:NSOperationQueue一共有兩種隊(duì)列:主隊(duì)列、其他隊(duì)列。其中其他隊(duì)列同時(shí)包含了串行、并發(fā)功能。下邊是主隊(duì)列、其他隊(duì)列的基本創(chuàng)建方法和特點(diǎn)。
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; //?< 主線程執(zhí)行
NSOperationQueue *otherQueue = [[NSOperationQueue alloc]init]; //?< 子線程執(zhí)行
3.2將任務(wù)添加到隊(duì)列
//僅以其它隊(duì)列舉例
NSOperationQueue *otherQueue = [[NSOperationQueue alloc]init]; //?< 子線程執(zhí)行
for (NSInteger i = 0; i < 0; i++) {
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是任務(wù)%ld %@",i,[NSThread currentThread]);
}];
//將任務(wù)添加到隊(duì)列中
[otherQueue addOperation:op];
}
當(dāng)我們將任務(wù)添加到隊(duì)列中時(shí),不需要我們手動(dòng)去開(kāi)始任務(wù),任務(wù)會(huì)自動(dòng)開(kāi)始
3.2隊(duì)列的最大并發(fā)數(shù)
最大并發(fā)數(shù)就是指在這個(gè)隊(duì)列里面的任務(wù)(如果是并行的隊(duì)列),最多一次可以執(zhí)行任務(wù)的個(gè)數(shù)。
舉個(gè)例子:用戶上傳100張照片,并且是異步的并發(fā)執(zhí)行,如果沒(méi)有設(shè)置最大并發(fā)數(shù)的話,那么這100個(gè)任務(wù)會(huì)一起執(zhí)行,且會(huì)影響性能,如果我們將最大并發(fā)數(shù)設(shè)置為10的話,則這個(gè)100個(gè)任務(wù)會(huì)被分成10組,每組10個(gè)任務(wù),10組任務(wù)間 一個(gè)一個(gè)執(zhí)行。
NSOperationQueue *otherQueue = [[NSOperationQueue alloc]init]; //?< 其它線程
//最大并發(fā)數(shù)
otherQueue.maxConcurrentOperationCount = 10;//?< 最大并發(fā)數(shù)
for (NSInteger i = 0; i < 100; i++) {
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是任務(wù)%ld %@",i,[NSThread currentThread]);
[otherQueue addOperation:op];
}];
3.3隊(duì)列添加任務(wù)的其它方法(Block)
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperationWithBlock:^{
//這里直接放任務(wù) 就可以了
NSLog(@"我是block的任務(wù) %@",[NSThread currentThread]);
}];
4任務(wù)的依賴關(guān)系
相比GCD來(lái)說(shuō),NSOperation在設(shè)置依賴關(guān)系上要比GCD方便的多只需要很少的代碼就可以完成。假設(shè)需求: 2 , 3任務(wù)都完成后 再去完成op1;如果是GCD的話,我們可以用信號(hào)量、barrier來(lái)實(shí)現(xiàn)我們的效果,但是一般實(shí)現(xiàn)起來(lái)稍微有些麻煩,下面我們來(lái)看下NSOperation是如何來(lái)設(shè)置依賴關(guān)系的
// 任務(wù) 添加依賴關(guān)系
//創(chuàng)建兩個(gè)隊(duì)列
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
NSOperationQueue *otherQueue = [[NSOperationQueue alloc]init];
//創(chuàng)建3個(gè)任務(wù)
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"任務(wù)1 %@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"任務(wù)2 %@",[NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"任務(wù)3 %@",[NSThread currentThread]);
}];
// 2 , 3任務(wù)都完成后 在完成op1
[op1 addDependency:op2];
[op1 addDependency:op3];
[otherQueue addOperation:op3];
[mainQueue addOperation:op2];
[otherQueue addOperation:op1];
//不受隊(duì)列的影響 隨意依賴
其中addDependency就是設(shè)置依賴關(guān)系的方法,只要一句就夠了,值得注意的是,所謂的依賴關(guān)系指的是任務(wù)之間的關(guān)系,而不是隊(duì)列的關(guān)系。