iOS進程和線程

1. 什么是程序、進程、線程

1.1 程序:

由源代碼生成的可執(zhí)行應(yīng)用。(例如:QQ.APP)

1.2 進程:

一個正在運行的程序可以看做一個進程。(例如:正在運行的QQ就是一個進程),進程擁有獨立運行所需的全部資源。

1.3 線程:

程序中獨立運行的代碼段。(例如:接收QQ消息的代碼)
一個進程是由一或多個線程組成。進程只負責資源的調(diào)度和分配,線程才是程序真正的執(zhí)行單元,負責代碼的執(zhí)行。

2. 單線程與多線程有什么區(qū)別

2.1單線程

每個正在運行的程序(即進程),至少包含一個線程,這個線程叫主線程。
主線程在程序啟動時被創(chuàng)建,用于執(zhí)行main函數(shù)。
只有一個主線程的程序,稱作單線程程序。
主線程負責執(zhí)行程序的所有代碼(UI展現(xiàn)以及刷新,網(wǎng)絡(luò)請求,本地存儲等等)。這些代碼只能順序執(zhí)行,無法并發(fā)執(zhí)行。

2.2多線程

擁有多個線程的程序,稱作多線程程序。
iOS允許用戶自己開辟新的線程,相對于主線程來講,這些線程,稱作子線程。
可以根據(jù)需要開辟若干子線程
子線程和主線程是 都是 獨立的運行單元,各自的執(zhí)行互不影響,因此能夠并發(fā)執(zhí)行。

2.3區(qū)別

單線程程序:只有一個線程,代碼順序執(zhí)行,容易出現(xiàn)代碼阻塞(頁面假死)。
多線程程序:有多個線程,線程間獨立運行,能有效的避免代碼阻塞,并且提高程序的運行性能。
注意:iOS中關(guān)于UI的添加和刷新必須在主線程中操作。

3. iOS多線程實現(xiàn)種類

主要由四種:NSThread、NSoperationQueue、NSobject、GCD

1.1輕量級別的多線程技術(shù),

需要我們手動管理線程,還有提供的方法比較少,例如:串行,并發(fā)執(zhí)行這些實現(xiàn)起來相當困難,開辟子線程的方法有兩種,這個需要我盟手動開啟線程,也就是start方法,并且有返回值,返回值就是NSThread對象,可以設(shè)置線程名稱,設(shè)置線程的權(quán)限的等級一些操作參數(shù)。另一個是便利構(gòu)造器的方法開辟子線程,無返回值,會自動啟動線程,不需要手動調(diào)用start方法。
#pragma mark -- NSThread 開辟子線程
// NSThread是我們自己手動開辟的子線程,如果使用的是初始化方式就需要我們自己是釋放,如果使用的是便利構(gòu)造器方式它就會自動啟動,只要是我們手動開辟的線程,都需要我夢自己管理該線程,不只是啟動,還有該線程使用完畢后的資源回收,所以在NSThread的回調(diào)方法中需要加入自動釋放池來回收資源
- (void)threadInfo{
    // object:這個是回調(diào)方法的參數(shù);
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(testThread:) object:@"我是參數(shù)"];
    // 當使用初始化方法出來的主線程需要start啟動
    [thread start];
    //    NSLog(@"我是逗比");
    // 可以為開辟的子線程起名字
    thread.name = @"我是第二條線程";
    // 調(diào)整Thread的權(quán)限 線程權(quán)限的范圍值為0 ~ 1 。越大權(quán)限越高,先執(zhí)行的概率就會越高,由于是概率,所以并不能很準確的的實現(xiàn)我們想要的執(zhí)行順序,默認值是0.5
    thread.threadPriority = 1;
    // 取消當前已經(jīng)啟動的線程
//    [thread cancel];
    // 通過遍歷構(gòu)造器開辟子線程
 //   [NSThread detachNewThreadSelector:@selector(testThread:) toTarget:self withObject:@"便利構(gòu)造器方式"];
    
}
1.2回調(diào)方法
如果子線程是我們手動開辟的,那么就需要我們來管理它運行所造成的資源回收
- (void)testThread:(NSString *)testString{
    // 如果子線程是我們手動開辟的,那么就需要我們來管理它運行所造成的資源回收
    @autoreleasepool {
        NSLog(@"參數(shù)----%@",testString);
        NSLog(@"testThread -- %@",[NSThread currentThread]);
        double sum = 0;
        for (int i = 1; i < 635500000; i ++) {
            sum += i;
        }
        NSLog(@"sum = %f---- %@",sum,[NSThread currentThread]);
        // 回到主線程 所有的NSObject對象或者NSobject的子類都有該方法,他是NSthread的另一種體現(xiàn)方式
        // waitUntilDone:是否將該回調(diào)方法執(zhí)行完在執(zhí)行后面的代碼,如果為YES:就必須等回調(diào)方法執(zhí)行完成之后才能執(zhí)行后面的代碼,說白了就是阻塞當前的線程,如果是NO:就是不等回調(diào)方法結(jié)束。不會阻塞當前線程

      // 回到主線程
        [self performSelectorOnMainThread:@selector(backMainThread) withObject:nil waitUntilDone:YES];
    }
}
- (void)backMainThread{
      NSLog(@"回到主線程");
}

2.NSObject

只要是NSObject的子類或者對象都可以通過調(diào)用方法進入子線程和主線程,其實這些方法所開辟的子線程也是NSThread的另一種體現(xiàn)方式。
開辟子線程:

[self performSelectorInBackground:@selector(aaa) withObject:nil];

進入主線程:

[self performSelectorOnMainThread:@selector(bbb) withObject:nil 
waitUntilDone:YES];

3.3.NSOperationQueue:他是將一組事件添加到隊列中,如果想讓這組事件是在主線程中執(zhí)行,那么就需要主隊列[NSOperationQueue mainQueue];如果想將一組事件在子線程中執(zhí)行那么就需要其他隊列[[NSOperationQueue alloc] init];NSOperationQueue就是事件,它本身是一個抽象類,如果需要實現(xiàn)具體操作,需要他的兩個子類
NSInvocationOperation和NSBlockOperation;事件本身與線程無關(guān),知識看你將他加到那種隊列中。如果加到隊列中想要是的時間順序執(zhí)行,需要給事件添加依賴關(guān)系,添加依賴關(guān)系的時候兩個事件不能互為依賴。也可以設(shè)置時間的優(yōu)先級來提高它先執(zhí)行的概率,但是不準確,還可以設(shè)置隊列最大并發(fā)行數(shù),來是事件順序執(zhí)行。

- (void)invocationOperationInfo{
    
    //  NSInvocationOperation 這個類只執(zhí)行一個操作,本身與線程無關(guān),意思就是,你把該類對象放到哪個線程里面,他就在那個線程中執(zhí)行
    NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(  invocationOperationAction) object:nil];
    // 改事件需手動執(zhí)行
    //    [invocationOperation start];
    // 通過Block方式增加一個事件
    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"block --- %@",[NSThread currentThread]);
        
    }];
    // block方式的operation可以增加一組額外的block事件,通過這種方式的blockOperation添加的block事件順序無法掌握沒所以線程無法掌控
    for (int i = 0; i < 5; i ++) {
        [blockOperation addExecutionBlock:^{
            NSLog(@"execuBlock %@",[NSThread currentThread]);
            
        }];
    }
    // 當所有的block事件都執(zhí)行完了,我們就可以讓他發(fā)出通知,告訴我們所有的事件都執(zhí)行完了
    blockOperation.completionBlock = ^{
        NSLog(@"不管上面的小弟怎么鬧,我是最后一個");
        NSLog(@"_____%@",[NSThread currentThread]);
        
    };
  
    // 主隊列  是將一組事件在主線程中執(zhí)行,不用設(shè)置任何屬性,一組事件都會順序執(zhí)行
    // 我們需要按照順序來執(zhí)行一組事件,轉(zhuǎn)讓個時候該怎么辦? 有兩種方式
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    // 第一種:設(shè)置隊列最大并發(fā)執(zhí)行事件的?個數(shù),該屬性默認值是-1;意思是:該隊列中有多少個事件,就并發(fā)執(zhí)行多少個,如果設(shè)置并發(fā)事件設(shè)置為1,那就是一次只執(zhí)行一個事件,
    //        queue.maxConcurrentOperationCount = 1;
    // 第二種:通過添加事件依賴,事件依賴的意思就是說:當?shù)匾粋€事件執(zhí)行完畢之后才執(zhí)行另一個事件,在這里就是先執(zhí)行invocationOperation,在執(zhí)行blockOperation,
    [blockOperation addDependency:invocationOperation];
    // 給隊列中增加事件
    [queue addOperation:invocationOperation];
    [queue addOperation:blockOperation];
}

4.GCD:

GCD效率比operationQueue要高一些,功能更強一些,目前有替代其他多線程的趨勢,他處理時間主要通過隊列來執(zhí)行,分為兩種隊列,一種是串行,另一中是并行,系統(tǒng)提供給我們的是全局隊列,一種是主隊列,添加時間函數(shù)為dispatch_async();一般我們都用一部添加事件,最重要的原因是他不會阻塞當前線程,全局隊列中所添加的異步事件坑定都是子線程中的,主隊列中添加事件不管同步還是異步都在主函數(shù)中運行;?。。?/h5>
一定記住會主線程要刷新UI原因是:1.iOS中為了效率更高,多數(shù)線程是沒有安全保證的,在子線程中刷新UI有可能會遇到不可預(yù)知的錯誤,2.在子線程中刷新UI,只有當前線程執(zhí)行完成,才會刷新UI,和可能造成UI刷新不及時,影響用戶體驗,而且一般只有主線程才有UI刷新功能

創(chuàng)建一個串行隊列

- (void)serialQueuueCuanXing{
    
    // 創(chuàng)建一個串行隊列
    // dispatch_queue_create 函數(shù)是用來創(chuàng)建隊列使用,第一個參數(shù)為該隊列的標簽,第二個參數(shù)為該隊列類型
    dispatch_queue_t serialQueue = dispatch_queue_create("串行", DISPATCH_QUEUE_SERIAL);
    // 給該隊列添加事件
    // 第一個參數(shù)為該事件所在的隊列,第二個參數(shù)為Block,該事件索要做的處理
    dispatch_sync(serialQueue, ^{
        NSLog(@"叼毛獸出生了---%@",[NSThread currentThread]);
    });
    dispatch_sync(serialQueue, ^{
        NSLog(@"叼毛獸會穿衣服了---%@",[NSThread currentThread]);
    });
    dispatch_sync(serialQueue, ^{
        NSLog(@"叼毛獸掛墻上了----%@",[NSThread currentThread]);
    });
    
     NSLog(@"執(zhí)行完了-- %@",[NSThread currentThread]);
    
}

創(chuàng)建一個并行隊列

// 并行隊列
- (void)seriaQueueBingXing{
    dispatch_queue_t seriaQueue = dispatch_queue_create("并行", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(seriaQueue, ^{
        NSLog(@"我是第一---%@",[NSThread currentThread]);
    });

    dispatch_async(seriaQueue, ^{
        NSLog(@"我是第二---%@",[NSThread currentThread]);
    });
    // 此函數(shù)會阻塞當前線程,對主線程無影響。
    dispatch_barrier_async(seriaQueue, ^{
        NSLog(@"我正在執(zhí)行---%@",[NSThread currentThread]);
    });
    dispatch_async(seriaQueue, ^{
        NSLog(@"我是第三---%@",[NSThread currentThread]);
    });
    dispatch_async(seriaQueue, ^{
        NSLog(@"我是第四---%@",[NSThread currentThread]);
    });
    


}

5.系統(tǒng)提供的全局隊列

- (void)globalQueue{
    // 上面都是我們自主創(chuàng)建的隊列,一般使用中,我們都不會自己創(chuàng)建,而是使用系統(tǒng)提供的隊列,系統(tǒng)提供的隊列有全局隊列,在此隊列中可以添加多個異步事件,并發(fā)執(zhí)行
    // 一般我們都是使用系統(tǒng)提供的們不用自己創(chuàng)建
    // 第一個參數(shù)為該全局隊列的優(yōu)先級
    // 第二個參數(shù)暫時沒用,是系統(tǒng)為后面擴展來使用的,在將來的某一天使用到,直接賦0就可以了
    
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(globalQueue, ^{
        NSLog(@"正在網(wǎng)絡(luò)下載或者其他一些耗時操作");
        // 耗時操作完成之后回主線程更新UI,GCD回主線程方式
        // 要得到主隊列,和operationQueue中的mainQueue是一樣的概念
        dispatch_queue_t mainQueue = dispatch_get_main_queue();
        dispatch_async(mainQueue, ^{
            // 在此處進行UI刷新
            NSLog(@"mainQueue -- %@",[NSThread currentThread]);
            
        });
        
    });
    
}
最后編輯于
?著作權(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)容

  • Object C中創(chuàng)建線程的方法是什么?如果在主線程中執(zhí)行代碼,方法是什么?如果想延時執(zhí)行代碼、方法又是什么? 1...
    AlanGe閱讀 1,908評論 0 17
  • 從哪說起呢? 單純講多線程編程真的不知道從哪下嘴。。 不如我直接引用一個最簡單的問題,以這個作為切入點好了 在ma...
    Mr_Baymax閱讀 2,902評論 1 17
  • 多線程 在iOS開發(fā)中為提高程序的運行效率會將比較耗時的操作放在子線程中執(zhí)行,iOS系統(tǒng)進程默認啟動一個主線程,用...
    郭豪豪閱讀 2,719評論 0 4
  • 線程、進程 1.iOS中的多線程操作、多線程方式? 2.多線程的優(yōu)點和缺點分別是什么? 答:優(yōu)點:1、將耗時較長的...
    丶逐漸閱讀 1,466評論 0 8
  • 關(guān)中大地今天迎來初雪的洗禮,狂魔亂舞般的雪飄肆虐地趕走空氣里的塵埃,也像是為人類洗肺! 我是一個不能承受散場的人,...
    修煉中的小妖閱讀 176評論 0 0

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