iOS 多線程小結(jié)

寫(xiě)此文章是為了能夠加深自己的記憶,并且對(duì)技術(shù)點(diǎn)有個(gè)記錄,方便查閱
這篇文章主要寫(xiě)一些iOS多線程的操作
1.NSThread([θred], 英式發(fā)音):輕量級(jí)的,編程中很少用,需要自己管理線程,加鎖等,很復(fù)雜,所以平時(shí)編程很少用。
比較常用的是獲取當(dāng)前線程和暫停當(dāng)前線程
- (void)textAction {
    NSThread *current = [NSThread currentThread];
    NSLog(@"current:%@",current);
    
    [NSThread sleepForTimeInterval:2];
    NSLog(@"finish");
}
2.引自百度百科
Grand Central Dispatch(GCD) 是 Apple 開(kāi)發(fā)的一個(gè)多核編程的較新的解決方法。它主要用于優(yōu)化應(yīng)用程序以支持多核處理器以及其他對(duì)稱多處理系統(tǒng)。它是一個(gè)在線程池模式的基礎(chǔ)上執(zhí)行的并發(fā)任務(wù)。在 Mac OS X 10.6 雪豹中首次推出,也可在 iOS 4 及以上版本使用。
GCD有一套完整的api,使用方便,也應(yīng)該是在實(shí)際開(kāi)發(fā)中用的最多的
GCD中有同步(sync)和異步之分(async),串行和并行隊(duì)列之分
串行隊(duì)列(Serial Dispatch Queue):
并行隊(duì)列(Concurrent Dispatch Queue):
GCD自帶的兩個(gè)隊(duì)列:
//主線程,串行
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//全局隊(duì)列,并行
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//自定義串行
dispatch_queue_t serialQueue = dispatch_queue_create("com.kevin.abcd", DISPATCH_QUEUE_SERIAL);
//自定義并行
dispatch_queue_t concurrentQueue =dispatch_queue_create("com.kevin.efgh", DISPATCH_QUEUE_CONCURRENT);


dispatch_queue_t queue;
//異步,會(huì)開(kāi)啟新線程
dispatch_async(queue, ^{
        //
});
//同步,不會(huì)開(kāi)啟新線程
dispatch_sync(queue, ^{
        //
});

用的比較多的其實(shí)是主線程刷新ui

    dispatch_async(dispatch_get_main_queue(), ^{
        //
    });
還有任務(wù)組,比如需要把兩個(gè)請(qǐng)求的結(jié)果合并為一個(gè),那么可以是兩個(gè)異步的請(qǐng)求加入dispatch group,等待兩個(gè)都返回后,調(diào)用group的通知,會(huì)告知我們?nèi)蝿?wù)組里的任務(wù)都完成了
    dispatch_queue_t concurrentQueue =dispatch_queue_create("com.kevin.efgh", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, concurrentQueue, ^{
        //執(zhí)行第一個(gè)任務(wù)
    });
    dispatch_group_async(group, concurrentQueue, ^{
        //執(zhí)行第二個(gè)任務(wù)
    });
    dispatch_group_notify(group, concurrentQueue, ^{
        //group 中的任務(wù)執(zhí)行完
    });
另外需要注意的是在dispatch_group_async中如果執(zhí)行的是異步操作的話,則notify會(huì)失效,需要用
//確保配對(duì)使用
        dispatch_group_enter(group);
        dispatch_group_leave(group);
gcd還有許多平常我們經(jīng)常用的的,例如單利的創(chuàng)建
+(instancetype)sharedInstance \
{ \
static CLASS * sharedInstance = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
sharedInstance = [[CLASS alloc] init]; \
}); \
return sharedInstance; \
}
有時(shí)我們需要延遲執(zhí)行一些操作
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
       // code to be executed after a specified delay
});
如果需要執(zhí)行兩組任務(wù),第一組必須在第二組之前運(yùn)行,則可以用柵欄函數(shù)解決
    dispatch_queue_t concurrentQueueTwo = dispatch_queue_create("com.kevin.concue=rrent", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(concurrentQueue, ^{
        NSLog(@"1");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"2");
    });
    dispatch_barrier_async(concurrentQueue, ^{
        NSLog(@"barrier");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"3");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"4");
    });
gcd還提供線程等待的方法,dispatch_group_wait
gcd中的信號(hào)量semaphore([?sem?f?:(r)])
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//創(chuàng)建總數(shù)為0的信號(hào)
dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信號(hào),當(dāng)信號(hào)量少于0時(shí)就會(huì)一直等待,否則正常執(zhí)行,并使信號(hào)量-1
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//創(chuàng)建總數(shù)為0的信號(hào)
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"1:%@",[NSThread currentThread]);
//        dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
    });
//    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信號(hào),當(dāng)信號(hào)量少于0時(shí)就會(huì)一直等待,否則正常執(zhí)行,并使信號(hào)量-1
    NSLog(@"5");
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"2:%@",[NSThread currentThread]);
//        dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
    });
    NSLog(@"6");
    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"3:%@",[NSThread currentThread]);
//        dispatch_semaphore_signal(semaphore);//+1
    });
    NSLog(@"7");
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"4:%@",[NSThread currentThread]);
//        dispatch_semaphore_signal(semaphore);//+1
    });
//    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
    NSLog(@"end:%@",semaphore);
6后面的不會(huì)執(zhí)行,信號(hào)量小于0,輸出如下
2018-03-29 17:48:55.679397+0800 TestProject[28407:3448511] 5
2018-03-29 17:48:55.679560+0800 TestProject[28407:3448511] 6
2018-03-29 17:48:57.682849+0800 TestProject[28407:3448635] 2:<NSThread: 0x6040002647c0>{number = 4, name = (null)}
2018-03-29 17:48:57.682849+0800 TestProject[28407:3448618] 1:<NSThread: 0x608000270d80>{number = 3, name = (null)}
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//創(chuàng)建總數(shù)為0的信號(hào),線程數(shù)1
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"1:%@",[NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
    });
    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信號(hào),當(dāng)信號(hào)量少于0時(shí)就會(huì)一直等待,否則正常執(zhí)行,并使信號(hào)量-1
    NSLog(@"5");
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"2:%@",[NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
    });
    NSLog(@"6");
    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"3:%@",[NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);//+1
    });
    NSLog(@"7");
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"4:%@",[NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);//+1
    });
//    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
    NSLog(@"end:%@",semaphore);
會(huì)等待1執(zhí)行完,輸出結(jié)果如下
2018-03-29 17:53:34.184881+0800 TestProject[28427:3460477] 1:<NSThread: 0x60c000271880>{number = 3, name = (null)}
2018-03-29 17:53:34.185061+0800 TestProject[28427:3460368] 5
2018-03-29 17:53:34.185161+0800 TestProject[28427:3460368] 6
2018-03-29 17:53:36.187280+0800 TestProject[28427:3460477] 2:<NSThread: 0x60c000271880>{number = 3, name = (null)}
2018-03-29 17:53:36.187442+0800 TestProject[28427:3460368] 7
2018-03-29 17:53:36.187581+0800 TestProject[28427:3460368] end:<OS_dispatch_semaphore: 0x60c000091d50>
2018-03-29 17:53:38.190267+0800 TestProject[28427:3460476] 4:<NSThread: 0x60c00026f540>{number = 4, name = (null)}
2018-03-29 17:53:38.190230+0800 TestProject[28427:3460477] 3:<NSThread: 0x60c000271880>{number = 3, name = (null)}

GCD控制并發(fā)數(shù)量
- (void)testSemaphoreTest{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);//所開(kāi)線程數(shù)為n+1
    for (int i=0; i<100; ++i) {
        dispatch_async(queue, ^{
            [NSThread sleepForTimeInterval:0.5];
            NSLog(@"number:%d thread:%@",i,[NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);//發(fā)送信號(hào),信號(hào)+1
        });
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    }
}
3.NSOperation是蘋(píng)果提供給我們的一套多線程解決方案。比GCD擁有更強(qiáng)的可控性和代碼可讀性,比如我們想cancel一個(gè)任務(wù),控制任務(wù)的優(yōu)先級(jí),用NSOperation就會(huì)很方便。
operation queues顧名思義是用來(lái)存放operation的隊(duì)列,可以通過(guò)設(shè)置最大并發(fā)數(shù)(maxConcurrentOperationCount)來(lái)控制并發(fā),串行。
maxConcurrentOperationCount 默認(rèn)情況下為-1,表示不進(jìn)行限制,可進(jìn)行并發(fā)執(zhí)行。
maxConcurrentOperationCount 為1時(shí),隊(duì)列為串行隊(duì)列。只能串行執(zhí)行
maxConcurrentOperationCount 大于1時(shí),隊(duì)列為并發(fā)隊(duì)列。操作并發(fā)執(zhí)行,當(dāng)然這個(gè)值不應(yīng)超過(guò)系統(tǒng)限制,即使自己設(shè)置一個(gè)很大的值,系統(tǒng)也會(huì)自動(dòng)調(diào)整為 min{自己設(shè)定的值,系統(tǒng)設(shè)定的默認(rèn)最大值}
nsoperation 自帶依賴的建立,很方便
-(void)testOperationDependency {
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        //
        NSLog(@"1");
    }];
    
    NSBlockOperation *operationTwo = [NSBlockOperation blockOperationWithBlock:^{
        //
        [NSThread sleepForTimeInterval:5];
        NSLog(@"2");
    }];
    
    NSBlockOperation *operationThree = [NSBlockOperation blockOperationWithBlock:^{
        //
        NSLog(@"3");
    }];
    //1依賴于2的完成
    [operation addDependency:operationTwo];
    
    [queue addOperation:operation];
    [queue addOperation:operationTwo];
    [queue addOperation:operationThree];
    
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 本文首發(fā)于我的個(gè)人博客:「程序員充電站」[https://itcharge.cn]文章鏈接:「?jìng)魉烷T(mén)」[https...
    ITCharge閱讀 350,661評(píng)論 308 1,927
  • 1. GCD簡(jiǎn)介 什么是GCD呢?我們先來(lái)看看百度百科的解釋簡(jiǎn)單了解下概念 引自百度百科:Grand Centra...
    千尋_544f閱讀 500評(píng)論 0 0
  • 本篇博客共分以下幾個(gè)模塊來(lái)介紹GCD的相關(guān)內(nèi)容: 多線程相關(guān)概念 多線程編程技術(shù)的優(yōu)缺點(diǎn)比較? GCD中的三種隊(duì)列...
    有夢(mèng)想的老伯伯閱讀 1,088評(píng)論 0 4
  • 巴山蜀地,悶熱潮濕的夏夜,我關(guān)了燈,躺在床上仰望黑灰的天花板。 我住的這家小青旅在22樓,白天的時(shí)候,從窗前望出去...
    思寰閱讀 314評(píng)論 0 0
  • (四) 在阿蒙還回來(lái)的書(shū)里,多了一張樸素的書(shū)簽,無(wú)名詩(shī)人在那上面似乎不經(jīng)意地寫(xiě)道:當(dāng)你心中的音樂(lè)緩緩響起,那...
    陳士武閱讀 134評(píng)論 0 0

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