網絡上關于多線程的原理和用法的解釋,隨便一搜一大堆,但是那個寬泛過于學術性的解釋,我看著太費力了。
我就用自己比較容易理解的白話來記錄一下我學到的知識吧。
一、進程
在移動端,一個app就是一個進程,在內存中占用一定的空間。
在計算機里,一個程序就是一個進程,同樣也占用內存空間。
iOS同一時間點只有一個進程在使用CPU,只是系統把這個時間片分割地非常短,造成一種多個進程同時在執行的假象。
二、線程
一個進程的執行,必然從一個主線程開始。
整個應用可以由單個主線程運行,但是涉及到一些耗時的任務,例如打開淘寶app,必然要加載一大堆的圖片。
這時,如果只有單線程執行,程序必須等著圖片都加載完畢才能繼續往下執行,期間用戶的交互就不起作用,這樣用戶體驗很不好。
所以,這時就衍生出多線程的概念,可以開子線程給那些耗時的任務,在旁邊默默地執行,而不影響應用的大局。
主線程,一般用來處理主體的展示(例如控制器的切換)和交互事件。
子線程,一般用來處理耗時的任務。
當然,并不是線程越多越好,多線程的使用也是要慎重考慮。
三、同步和異步
我之前一直對同步和異步這個概念理解不清,常?;煜?。同步是線程安全呢,還是異步線程安全呢?
今天終于記清楚了這個概念,只要記住一句話——同步,就是同類;異步,就是異類。
已經是同類,那肯定是處于同一個線程;異類,那就說明不是一個線程。
四、并行和串行
并行:并發執行
串行:按順序執行,一個接一個
五、三種常用創建多線程方式
1、NSThread:程序員手動管理線程,而多線程的情況下,線程什么時候執行完畢是未知的,如果管理不好,會造成內存泄露,所以這種方法不提倡。
2 、NSOperation/NSOperationQueue。這兩個類必須是搭配使用的,將操作放入操作隊列中,依次執行。
1>使用步驟:
* 創建NSOperation
* 添加NSOperation到NSOperationQueue
2>優點:
* 更加面向對象
* 可以控制最大并發數 maxConcurrentOperationCount,使用這個屬性可以保證同一時間內最大的并發數
* 添加任務(Operation)之間的依賴 addDependency,使用這個屬性可以控制一個Operation必須在其依賴的Operation執行完畢后才調用
//1.首先聲明一個全局變量NSOperationQueue *_queue;//2.定義變量_queue = [[NSOperationQueue alloc] init];// 控制最大并發數:2_queue.maxConcurrentOperationCount = 2;//3.具體某個方法開啟多線程NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下載圖片-%@", [NSThread currentThread]);}]; NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"濾鏡處理-%@", [NSThread currentThread]);}]; // op1依賴于op(op執行完,才能執行op1)[op1 addDependency:op];//操作加入隊列[_queue addOperation:op];[_queue addOperation:op1];
3、GCD(官方推薦使用,純C語言)
調用同步(異步)執行的方法,傳入要并行(串行)執行的隊列參數,執行方法內的block代碼。
說白了就是同一時間有一個還是多個線程執行,就看調用的方法和傳入的隊列類型。
1> 隊列類型
* 全局隊列
* 所有添加到全局隊列中的任務都是并發執行(同時執行,可能會開啟多個線程)
* dispatch_get_global_queue
* 串行隊列
* 所有添加到串行隊列中的任務都是按順序執行(開一條線程)
* dispatch_queue_create("myqueue", 0);
* 主隊列
* 所有添加到主隊列中的任務都是在主線程中執行的(跟方法名沒有關系)
* dispatch_get_main_queue
2> 同步還是異步,取決于方法名(不影響主隊列,影響全局隊列、串行隊列)
* 同步:dispatch_sync,在當前線程執行任務,不會開啟新的線程
* 異步:dispatch_async,在其他線程執行任務,會開啟新的線程
3>代碼demo演示:
從組合學上說,總是共有四種情況:串行-同步、串行-異步、并行-同步、并行-異步。
串行-同步:顯然一直只有一個線程在執行(這個就是真正意義上單線程)
串行-異步:可能會產生多個線程,但是同一時間只有一個線程在執行(異步雖然會產生多個不同線程,但是同一時間只有一個線程在執行)
并行-同步:同一時間點有多個相同的線程在執行
并行-異步:同一時間有多個不同的線程在執行(這是真正意義上的多線程)
下面就只舉兩個例子,剩下的2種情況舉一反三就是了
//串行隊列,執行同步方法。說明只有一個線程在執行dispatch_queue_t queue = dispatch_queue_create("myqueue", 0);dispatch_sync(queue, ^{ // 耗時操作 NSLog(@"dispatch_async-%@", [NSThread currentThread]);});
//并行隊列,異步執行。說明同一時間多個線程一起執行dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_sync(queue, ^{ // 耗時操作 NSLog(@"dispatch_async-%@", [NSThread currentThread]);});
而主隊列的使用,常常用來執行完子線程后,要講數據返回主線程來進行處理。
比如開啟子線程下載某個資源,下載完畢需要回調到主線程來展示。
可以在子線程完成的時候調用以下的方法返回主線程,同時能夠將子線程得到的參數傳給處理的selector方法里執行。
[xxx performSelectorOnMainThread:@selector(xxx:) withObject:xxx waitUntilDone:YES]
4、開啟后臺線程
[self performSelectorInBackground:@selector(test) withObject:nil]
六、總結
多線程是很重要的點,這些只是我目前掌握的理解,可能有很多不足和理解偏差,以后慢慢改進,繼續補充。
新聞熱點
疑難解答