iOS多線程分析

進(jìn)程

1.正在進(jìn)行的一個(gè)過(guò)程或任務(wù),負(fù)責(zé)任務(wù)執(zhí)行的是cpu。
2.每個(gè)進(jìn)程之間是獨(dú)立的,每個(gè)進(jìn)程都運(yùn)行在獨(dú)立的內(nèi)存空間內(nèi),并擁有獨(dú)立運(yùn)行所需的全部資源。

線程

1.程序運(yùn)行時(shí)的最小單位,是進(jìn)程的實(shí)際運(yùn)作單位。
2.進(jìn)程想要執(zhí)行任務(wù)必須至少有一個(gè)線程。在應(yīng)用程序啟動(dòng)時(shí),系統(tǒng)會(huì)默認(rèn)開(kāi)啟一個(gè)線程,即主線程。

進(jìn)程和線程的關(guān)系

1.線程在進(jìn)程下進(jìn)行
2.一個(gè)進(jìn)程可以包含多個(gè)線程
3.同一個(gè)進(jìn)程內(nèi)不同的線程間數(shù)據(jù)容易共享
4.進(jìn)程是用內(nèi)存地址可以上鎖,即一個(gè)線程使用共享內(nèi)存時(shí),其他線程必須等待其結(jié)束,才能使用。(互斥鎖)
5.進(jìn)程使用的內(nèi)存地址也可以限定使用,即當(dāng)前只允許2 人訪問(wèn),第三人需要等待有人結(jié)束訪問(wèn)后再進(jìn)行訪問(wèn)。(信號(hào)量)
6.一個(gè)程序有多個(gè)進(jìn)程,一個(gè)進(jìn)程可以有多個(gè)線程,但每個(gè)進(jìn)程至少要有一個(gè)線程。

多線程

1.多條線程并發(fā)執(zhí)行,cpu快速的在多條線程之間調(diào)度。 如果cpu調(diào)度線程時(shí)間足夠的快,就造成了多線程并發(fā)的假象。
2.如果線程非常多,也會(huì)大量消耗cpu資源。
3.多線程可以提高程序的執(zhí)行效率,能適當(dāng)提高資源的利用率。
4.如果開(kāi)啟大量的線程會(huì)占用內(nèi)存空間,降低程序性能。

隊(duì)列

串行隊(duì)列

同一時(shí)間內(nèi),隊(duì)列中只能執(zhí)行一個(gè)任務(wù),當(dāng)前任務(wù)結(jié)束后才能執(zhí)行下一個(gè)任務(wù)。

并發(fā)隊(duì)列

同時(shí)允許多個(gè)任務(wù)并發(fā)執(zhí)行。

iOS中的多線程

GCD

1.獲取主線程

dispatch_queue_t main_queue = dispatch_get_main();

2.線程延時(shí)

/** 
DISPATCH_TIME_NOW : 現(xiàn)在
DISPATCH_TIME_FOREVER : 永遠(yuǎn)超時(shí)
NSEC_PER_SEC : 秒  (1000,000,000 納秒 = 1秒) 可精確到納秒級(jí),eg. 0.1 *  NSEC_PER_SEC 是0.1 * 1000,000,000 = 100,000,000 納秒 = 0.1秒 以下算法雷同。
NSEC_PER_MSEC : 毫秒 (1000,000 納秒  = 1 毫秒)可精確到毫秒級(jí)
USEC_PER_SEC : 秒   (1000000微秒 = 1秒) 可精確到微秒級(jí)
NSEC_PER_USEC : 微秒  (1000納秒 = 1 微秒) 可精確到納秒級(jí)
*/
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), main_queue, ^{
    NSLog(@"哈哈");
})

3.只執(zhí)行一次,常用作單例模式

static dispatch_once_t once;
dispatch_once(&once, ^{
     // 只實(shí)例化一次
     personModel = [[self alloc] init];
 });

4.線程組,即等待一組任務(wù)完成后繼續(xù)執(zhí)行下一步,常被應(yīng)用在圖片上傳

    // 開(kāi)啟全集并發(fā)線程,DISPATCH_QUEUE_PRIORITY_DEFAULT 是線程等級(jí), 0 是flag,備用字段,通常設(shè)置0
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, queue, ^{
       // 進(jìn)行操作1
    });
    dispatch_group_async(group, queue, ^{
       // 進(jìn)行操作2
    });
    dispatch_group_async(group, queue, ^{
       // 進(jìn)行操作3
    });
    
    dispatch_group_notify(group, queue, ^{
       // 操作1。2。3 執(zhí)行完畢 進(jìn)行 下一步操作
    });
    // 超時(shí)等待,即設(shè)置一個(gè)最長(zhǎng)等待時(shí)常,超過(guò)時(shí)間后 調(diào)起 notify block
    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

5.信號(hào)量,設(shè)置最大并發(fā)線程數(shù),設(shè)置數(shù)大于1時(shí)順序不能保證

//創(chuàng)建信號(hào)量, 2為設(shè)置最大并發(fā)線程
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
    for (int i = 0; i < 5; i++) {
        // 創(chuàng)建異步線程
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            // 信號(hào)量的等待時(shí)長(zhǎng),這里設(shè)置為一直等待,當(dāng)信號(hào)量小于0 時(shí)一直等待,如果大于1則進(jìn)入且降低信號(hào)量即-1
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            // 睡眠2秒
            sleep(2);
            // po 出當(dāng)前線程, 顯示log
            NSLog(@"%@", [NSThread currentThread]);
            // 標(biāo)記信號(hào)量 + 1
            dispatch_semaphore_signal(semaphore);
            
        });
    }
    
    for (int i = 0; i < 5; i++) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            sleep(2);
            NSLog(@"%@", [NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);
            
        });
    }

NSOPeration

NSOperation是基于GCD的抽象基類(lèi)。
NSOperation可以跨隊(duì)列設(shè)置依賴(lài)關(guān)系
NSOperation面向?qū)ο?,支持KVO,可以檢測(cè)operation是否正在執(zhí)行,是否結(jié)束或者取消
NSOperation實(shí)體子類(lèi)有兩個(gè),NSBlockOperation 和 NSInvocationOperation

    // 初始化 方法實(shí)例
    NSInvocationOperation *invoOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(haha:) object:nil];
    [invoOperation start];
    // 初始化 block塊 實(shí)例
    NSBlockOperation *blockOpertaion = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"ni hao ");
    }];
// 繼續(xù)添加線程
blockOperation add
    [blockOpertaion start];
    // 以下為 依賴(lài)關(guān)系
    // 獲取 主線程
    NSOperationQueue *main_Operation = [NSOperationQueue mainQueue];
    // 創(chuàng)建 各種線程
    NSOperation *person_a = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"我是 神秘人 A");
    }];
    NSOperation *person_b = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"我是 神秘人 B");
    }];
    NSOperation *person_c = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"我是 神秘人 C");
    }];
    // 添加依賴(lài)關(guān)系, A以來(lái) B和C ,相當(dāng)于 A要在 B C 之后才能執(zhí)行任務(wù)
    [person_a addDependency:person_b];
    [person_a addDependency:person_c];
    
    //添加到 主線程中 查看順序
    [main_Operation addOperation:person_a];
    [main_Operation addOperation:person_b];
    [main_Operation addOperation:person_c];

NSThread

NSThread使用比較簡(jiǎn)單,可以靜態(tài)獲取線程信息

 // 獲取主線程
    NSThread *thread = [NSThread mainThread];
    // 判斷是否開(kāi)啟了多線程
    BOOL isOpenThread = [NSThread isMultiThreaded];
    // 獲取當(dāng)前線程
    NSThread *currentThread = [NSThread currentThread];
    // 當(dāng)前線程睡眠 時(shí)間(s) 10秒鐘
    [NSThread sleepForTimeInterval:10];
    //  睡眠到指定時(shí)間 , 以下為當(dāng)前時(shí)間往后延10秒鐘
    [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
    // 退出當(dāng)前線程 , 禁止在主線程使用
    //[NSThread exit];

    // 初始化線程對(duì)象  實(shí)例化對(duì)象
    /*
     qualityOfService 線程的優(yōu)先級(jí)
     NSQualityOfServiceUserInteractive 最高級(jí)別,用于UI交互,點(diǎn)擊事件,繪制圖形等
     NSQualityOfServiceUserInitiated = 次高級(jí)別,用于執(zhí)行立即返回的任務(wù)
     NSQualityOfServiceUtility 普通級(jí)別,不需要立即返回的任務(wù)
     NSQualityOfServiceBackground 后臺(tái)級(jí)別,完全不緊急的任務(wù)
     NSQualityOfServiceDefault 默認(rèn)級(jí)別
     */
    NSLog(@"%@", [NSThread currentThread]);
    NSThread *asynThread = [[NSThread alloc] initWithTarget:self selector:@selector(hello) object:nil];
    // 設(shè)置 線程實(shí)例化對(duì)象的 優(yōu)先級(jí)別,默認(rèn)為 默認(rèn)級(jí)別
    asynThread.qualityOfService = NSQualityOfServiceDefault;
    // 開(kāi)始線程
    [asynThread start];
    
    // 也可以快速創(chuàng)建線程
    [NSThread detachNewThreadSelector:@selector(hello) toTarget:self withObject:nil];
    __weak typeof(self) weakSelf = self;
    [NSThread detachNewThreadWithBlock:^{
        // po 出當(dāng)前線程
        NSLog(@"%@", [NSThread currentThread]);
        // 回到主線程
        [weakSelf performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
    }];

    // 還有一些 創(chuàng)建線程的方法
    // 3 秒后執(zhí)行 hello 方法 , 在當(dāng)前線程
    [self performSelector:@selector(hello) withObject:nil afterDelay:3];
    // 后臺(tái)異步執(zhí)行
    [self performSelectorInBackground:@selector(hello) withObject:nil];
    // 在主線程上執(zhí)行 hello 方法
    [self performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
    // 在 指定的 asynThread 線程上執(zhí)行 hello方法  *** 注意避免在子線程中執(zhí)行 ui交互
    [self performSelector:@selector(hello) onThread:asynThread withObject:nil waitUntilDone:NO];
最后編輯于
?著作權(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)容

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