多線程技術 NSThread & NSOperation & GCD,多線程技術nsthread
多線程:在iOS開發中,用到多線程的處理問題的時候有很多,比如非同步下載資料時重新整理介面等等。
引入多線程來處理問題的關鍵就是,基於多線程可以使介面更加流暢,防止介面假死。
介面假死:比如你單擊一個按鈕來開啟一個線程,但是這個線程處理的時間是10s,如果你線上程執行完成前再次點擊按鈕,就會造成一個介面假死的現象,因此引入多線程來處理問題。
1、NSThread 每個NSThread對象對應一個線程,量級較輕(真正的多線程)
以下兩個是蘋果專門開發的“並發”技術,使得程式員可以不再去關心線程的具體使用問題 ;
2、NSOperation 物件導向的線程技術 ;
3、GCD —— Grand Central Dispatch(派發) 是基於C語言的架構,可以充分利用多核,是蘋果推薦使用的多線程技術,個人認為是iOS系統下的一款基於block實現的多線程技術。
(1).
NSThread建立線程方法:
(void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;
(id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
參數說明:
selector:線程執行的方法,只能有一個參數,不能有傳回值
target:selector訊息發送的對象
argument:傳輸給target的唯一參數,也可以是nil
// 成員方法
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(bigDemo) object:nil];
// 啟動start線程
[thread start];
(2).
NSOperation的兩個子類
NSInvocationOperation
NSBlockOperation
工作原理:
用NSOperation封裝要執行的操作
將建立好的NSOperation對象放NSOperationQueue中
啟動OperationQueue開始新的線程執行隊列中的操作
注意事項:
使用多線程時通常需要控制線程的並發數,因為線程會消耗系統資源,同時啟動並執行線程過多,系統會變慢
使用以下方法可以控制並發的線程數量:
NSOperation 是放入到NSOperationQueue中實現的,這種建立線程的方法是多是給一些不懂多線程的人員開發用的。
下面我簡單介紹一下NSOperationQueue:
所謂的NSOperationQueue,雖然名稱也是一個Queue(隊列),其實實質上本身執行起來並不是嚴格按照隊列的先進先出的順序執行的,所以我一般稱之為線程池,它本身的機制本身就相當於你去銀行去辦理業務,也許你到銀行比較早,但是在你排隊的過程中,另外一個人本身比你來的晚,但是你們分別到了不同的服務視窗進行辦理業務,而比你到銀行晚的那個人辦理的業務比較少,而你辦理的業務比較多,因此最後他會先辦理好離開銀行,因此我認為可以理解為NSOperationQueue是一個線程池。
- 比較重要的一點是:用NSOperation建立線程的話,需要返回主線程,返回主線程的方法是:performSelectorOnMainThread:@selector(func) withObject: waitUntilDone:
(3).
有兩種方式實現GCD.
第一種 使用線程隊列,有兩個步驟,
第一步:建立線程隊列
第二步:非同步執行線程隊列
第二種 使用線程組(常用,當線程組中,可以有通知主線程的方法),有三個步驟
第一步:建立線程組
第二步:建立線程隊列
第三步:將線程隊列放到線程組種,非同步執行線程組
第一種方式: 線程隊列
/01 建立線程隊列
dispatch_queue_t thread=dispatch_queue_create(NULL, NULL);
//02 非同步執行線程隊列(也就是在,在這個線程隊列中,要做什麼事)
dispatch_async(thread, ^{
sleep(2);
NSLog(@"休眠2s");
});
//也可以通過 dispatch_get_global_queue(0, 0) 得到閑置的線程隊列,如果沒有,則會自動建立一個現場隊列。
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(2);
NSLog(@"休眠2s");
});
第二種方式:線
//01 建立線程組
dispatch_group_t threadGroup=dispatch_group_create();
/02 建立線程隊列
dispatch_queue_t t=dispatch_queue_create(NULL, NULL);
//03 將線程隊列放入到線程組中,
dispatch_group_async(threadGroup, t, ^{
sleep(2);
NSLog(@"休眠2s");
});
//這裡又可使用閑置線程隊列
dispatch_group_async(threadGroup, dispatch_get_global_queue(0, 0), ^{
sleep(2);
NSLog(@"休眠2s");
});
/*
使用線程組有一個好處就是 當線程組的線程隊列已經全部執行完畢後 可以通知 主線程
*/
dispatch_group_notify(threadGroup, dispatch_get_main_queue(), ^{
NSLog(@"線程組的線程隊列已經全部執行完畢。回到主線程");
});
//驗證 是否是線程組中的線程隊列全部執行完畢後,才調用 通知的
//經過驗證 的確是當線程組中的線程隊列全部執行完畢後,才開始 通知
dispatch_group_async(threadGroup, dispatch_get_global_queue(0, 0), ^{
sleep(3);
NSLog(@"休眠3s");
});