多執行緒(pthread,NSThread,GCD)
1.什麼是執行緒?
2.什麼是程式?
3.什麼又是多執行緒?
程式就是指在系統中正在執行的應用程式.
每個程式之間是獨立的, 每個程式均執行在其專用且受保護的記憶體內.
執行緒是程式的一條執行路徑.
執行緒注意點:
1>執行緒執行任務是序列的. (所以才有了子執行緒的概念, 如果都放在一個執行緒中執行任務, 當下載大圖片的時候, 就什麼操作也做不了了. .....)
關於多執行緒:
一個程式中可以開啟多個執行緒, (一個應用程式中能夠開啟多個通道, 讓不同的任務進行執行, 而不會導致 阻塞).
這樣在同一時間內, 既不影響使用者的體驗, 也將大資料/耗時操作 得以執行.
關於多執行緒的原理:
1.同一時間,CPU只能處理一條執行緒, 只有一條執行緒在工作(執行)
2.多執行緒併發(同時)執行,其實是CPU快速的在多條執行緒之間排程(切換).
3.如果CPU排程執行緒的時間足夠快,就造成了多執行緒併發執行的假象.
思考:如果執行緒很多時,會出現什麼情況?
1>CPU會在多個執行緒之間排程, 累死了,消耗了大量的CPU資源
2>每條執行緒被排程執行的頻率降低( 會很卡的).
多執行緒的優缺點:
優點:
1>能適當提高程式的執行效率.
2>適當的提高資源利用率
缺點:
1>建立執行緒是有開銷的. 建立時間大約 90毫秒, 佔用一定記憶體資源
2>大量的開啟執行緒, 會降低程式的效能.
3>執行緒越多, CPU在排程執行緒上的開銷就越大(無故消耗資源)
4>程式設計更加複雜,執行緒之間的通訊, 以及資源共享等問題
多執行緒在iOS開發中的應用:
1>主執行緒: 和程式的啟動有關, 程式已啟動,預設開啟一個主執行迴圈, 內部有一個主執行緒.(UI執行緒)
2>主執行緒的主要作用:
顯示/重新整理UI介面 (一般都是一部請求資料, 會主執行緒重新整理UI)
處理UI事件(比如 點選, 拖拽,滾動等)
3>使用主執行緒需要注意的
不要將耗時操作放置在主執行緒執行. (阻塞主執行緒 , 嚴重影響UI的流暢度)
pthread(純C語言, 比較難使用,這裡只進行簡單方法的說明)
// 點選螢幕增加子執行緒 ,來執行耗時的 方法.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 將耗時操作放在子執行緒中執行
pthread_t thread;
/*
第一個的引數:執行緒的代號(就是代指執行緒)
第二個引數:執行緒的屬性
第三個引數:只想指向函式的指標,就是執行緒需要執行的方法
第四個引數: 就是指向函式的指標 傳遞的引數。
*/
pthread_create(&thread, NULL,&demo , "lxl");
// 用於驗證 ,主執行緒繼續執行操作 (沒有阻塞主執行緒)
NSLog(@"劉小龍,你好,%@",[NSThread currentThread]);
}
// 設定耗時的方法 ( 只想函式的指標)
void *demo(void *parma){
// 列印傳入的引數, 以及當前的執行緒, 是1則是主執行緒,其他都不是
NSLog(@"%s,%@",parma,[NSThread currentThread]);
// 一些耗時的操作
for (int i = 0; i < 99999; i++) {
// NSLog是一個非常耗時的操作
// 上架之前 全部清掉.
NSLog(@"%i",i);
}
return NULL;
}
NSThread(不長使用, 需要自己手動管理它的生命週期) [現在使用它只有一個目的 就是獲取當先所處的執行緒 [NSThread currentThread] ]
建立和啟動執行緒
1>一個NSThread物件就代表一個執行緒.
2>建立.啟動執行緒 (直接設定執行緒的執行者, 和執行緒執行的方法, 傳入的引數)- initWithTarget:<#(nonnull id)#> selector:<#(nonnull SEL)#> object:<#(nullable id)#>
- start
開啟執行緒
3>常用的與主執行緒相關的方法:+ mainThread
獲得主執行緒- isMainThread
是否是主執行緒+ isMainThread
是否為主執行緒+ currentThread
獲取當前的執行緒- setName:
設定執行緒的名字,方便管理
4> 建立一個直接啟動的執行緒(不能設定名字)+ detachNewThreadSelector: toTarget: withObject:
5>隱式建立並啟動執行緒(一般我都不會這麼用,不好管理)
[self performSelectorInBackground:@selector(run) withObject:nil];
執行緒的狀態
1>啟動執行緒
- start
進入就緒狀態--->執行狀態. 執行緒任務執行完畢,自動進入死亡狀態2>阻塞(暫停)執行緒
+ sleepUntilDate:
// 執行緒休眠到什麼時候+ sleepForTimerInterval:
// 休眠幾秒阻塞執行緒
3>強制停止執行緒
+ exit
進入死亡狀態 ---一旦執行緒停止(死亡), 就不能再次開啟任務, 需要重新定義.#############
1.建立子執行緒:新建
2.就緒:啟動子執行緒
3.執行:排程子執行緒
4.阻塞:呼叫了sleep/等待同步鎖 @synchronized(id){}
5.死亡:執行緒執行完畢,或者異常退出/強制退出
注意: 對於執行緒物件,建立的時候被加到了 可排程執行緒池中, 待排程使用。 如果呼叫了sleep/同步鎖,就會被移除排程池,當sleep/同步鎖到時後,會再被引入排程池,做就緒準備
互斥鎖,與執行緒之間的搶奪, 已經在上文講出
執行緒之間的通訊
1>執行緒之間不是孤立存在的, 多個執行緒之間需要經常進行通訊.
2> 資料傳遞, 任務傳遞
3>常用方法[一般都是控制器自己呼叫的]- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)obj waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)the withObject:(id)arg waitUntilDone:(BOOL)wait
GCD (Grand Central Dispatch),"牛逼的中樞排程器"
1>純C語言,提供了很強的函式
2>優勢:
GCD是蘋果公司為多核的並行運算提出的解決方案
GCD會自動利用更多的CPU核心
GCD會自動管理執行緒的生命關係(建立執行緒,排程任務,銷燬執行緒)
程式設計師只需要告訴GCD想要執行什麼任務,不需要管理執行緒
3>任務與佇列
任務:執行什麼操作
佇列:用來存放任務
4>GCD的使用就2個步驟
定製任務
確定想做的事情
5>將任務新增到佇列中
執行緒---->佇列----->任務
任務加入佇列, 佇列放置線上程中執行
GCD會自動
將佇列中的任務取出,放到對應的執行緒中執行
任務的取出遵循佇列的FIFO原則:先進先出,後進後出.
########任務的執行
GCD常用的2個用來執行任務的常用函式
1>
1.同步的方式執行任務dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
queue:佇列 block:任務
2.非同步的方式執行任務dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
2>同步和非同步的區別
同步:只能在當前的執行緒中執行任務,不具備開啟新執行緒的能力
非同步:可以在新的執行緒中執行任務,具備開啟新執行緒的能力
3>執行任務
GCD中還有個來執行任務的函式:(新增依賴)dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
前面的佇列執行完任務後,才能執行後面的任務 ,這裡的佇列不能傳全域性併發佇列, 必須傳一個固定的佇列.
4>GCD的佇列可以分為2個型別:
併發佇列(Concurrent Dispatch Queue)
系統建立多條執行緒來併發(同時)執行佇列中的任務, 但開啟幾條,由系統決定, 這個佇列只有在非同步函式中有效果
序列佇列(Serial Dispatch Queue)
讓任務一個個執行 (一個任務執行完畢後,在執行下一個任務)
########同步/非同步;併發/序列
同步/非同步:能不能開啟新的執行緒
同步:只是在當前執行緒
(一般都是指主執行緒)中執行任務,不具備開啟新執行緒的能力.
非同步:可以在新的執行緒中執行任務,具備開啟新執行緒的能力
併發/序列:任務的執行方式
併發:允許多個任務併發(同時)執行
序列:一個任務執行完畢後,再執行下一個任務
5>併發佇列
5.1dispatch_queue_create
函式建立佇列
dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
lable: 佇列名稱
attr: 佇列的型別
簡單的建立併發佇列:
dispatch_queue_t queue = dispatch_queue_create("123",DISPATCH_QUEUE_CONCURRENT)
5.2全域性併發佇列dispatch_get_global_queue
函式獲得全域性的併發佇列
函式的書寫dispatch_queue_t dispatch_get_global_queue( dispatch_queue_priority_t priority ,// 佇列的優先順序 unsigned long flags //這個只是一個標誌, 一般不用 傳0)
優先順序預設也是0
6>序列佇列
6.1 dispatch_queue_create
函式建立序列佇列
建立序列佇列(佇列型別傳遞NULL 或者 DISPATCH_QUEUE_SERIAL)
簡單建立序列佇列
dispatch_queue_t queue = dispatch_queue_create("123",NULL)
6.2 使用主佇列 (跟主執行緒相關聯的佇列)
主佇列是GCD自帶的一種特殊的序列佇列
放在主佇列的任務,都會放在主執行緒中執行
使用dispatch_get_main_queue()
獲得主佇列
7>執行緒之間的通訊
子執行緒執行耗時操縱, 會主執行緒重新整理UI控制元件
dispatch_async(
dispatch_get_global_queue(0,0),^{
// 耗時的非同步操作
.....
#warning 必須使用非同步呼叫主佇列. 同步的話,會造成阻塞主執行緒(因為有矛盾, 主執行緒不想讓執行block, 主佇列又想, 這樣很矛盾的)
dispatch_async(dispatch_get_main_queue(),^{
// 返回主執行緒,執行UI重新整理操作
});
});
8>延遲執行
常見的幾種延遲執行的方法:
8.1 呼叫NSObject的方法
[self performSelector:@selector(run) withObject:nil afterDelay:2.0]; // 延時兩秒呼叫self的run方法
8.2使用GCD函式
dispatch_after(dispatch_time(DISPATCH_TIME_NOW , (int64_t)(2.0 * NSEC_PER_SEC)),dispatch_get_main_queue(),^{
// 2秒後執行這裡的程式碼......
});
8.3使用NSTimer
[NSTimer scheduledTimerWithTimeInterval: 2.0 target:self selector:@selector(test) useInfo:nil repeats:NO];
/##############特殊應用##############/
8.4一次性程式碼
使用dispatch_once函式能保證某段程式碼在程式執行過程中只被執行一次
static dispatch_once_t oneToken;
dispatch_once(&onceToken,^{
// 只執行一次的程式碼(在這裡預設是執行緒安全的)
});
8.5快速迭代
使用dispatch_apply函式能進行快速迭代遍歷
dispatch_apply(10,dispatch_get_global_queue(0,0),^(size_t index){
// 執行10次程式碼, index順序不確定
.....
})
8.6佇列組
有點等同於依賴的關係,
但是對於某些特殊要求還是需要建立佇列組來完成
比如有這麼一個需求
1>首先:分別非同步執行2個耗時操作
2>其次:等2個非同步操作都執行完畢後,再回到主執行緒執行操作
dispatch_group_t group = dispatch_group_creat();
dispatch_group_async(group,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0),
^{
//
執行1個耗時的非同步操作
});
dispatch_group_async(group,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0),
^{
//
執行1個耗時的非同步操作
});
dispatch_group_notify(group,
dispatch_get_main_queue(),
^{
//
等前面的非同步操作都執行完畢後,回到主執行緒...
});,,
相關文章
- iOS多執行緒(Pthread、NSThread、GCD、NSOperation)iOS執行緒threadGC
- iOS 多執行緒之NSThreadiOS執行緒thread
- 多執行緒——GCD執行緒GC
- pthread 多執行緒基礎thread執行緒
- iOS 多執行緒之NSThread和NSObjectiOS執行緒threadObject
- IOS多執行緒之(GCD)iOS執行緒GC
- iOS 多執行緒之GCDiOS執行緒GC
- iOS多執行緒GCD篇iOS執行緒GC
- 用Pthread實現多執行緒操作thread執行緒
- iOS多執行緒:GCD詳解iOS執行緒GC
- iOS多執行緒開發—GCD (一)iOS執行緒GC
- iOS 多執行緒:『GCD』詳盡總結iOS執行緒GC
- C++-(25)-多執行緒-POSIX(3)-互斥量-pthread_mutexC++執行緒threadMutex
- iOS多執行緒全套:執行緒生命週期,多執行緒的四種解決方案,執行緒安全問題,GCD的使用,NSOperation的使用iOS執行緒GC
- iOS 多執行緒--GCD 序列佇列、併發佇列以及同步執行、非同步執行iOS執行緒GC佇列非同步
- 多執行緒和多執行緒同步執行緒
- iOS底層原理 多執行緒之GCD 看我就夠了 --(10)iOS執行緒GC
- iOS多執行緒之GCD、OperationQueue 對比和實踐記錄iOS執行緒GC
- 執行緒與多執行緒執行緒
- 多執行緒【執行緒池】執行緒
- 多執行緒--執行緒管理執行緒
- iOS GCD執行緒之間的通訊iOSGC執行緒
- Java多執行緒-執行緒中止Java執行緒
- 多執行緒之初識執行緒執行緒
- 多執行緒------執行緒與程式/執行緒排程/建立執行緒執行緒
- 多執行緒系列(1),多執行緒基礎執行緒
- a、多執行緒執行緒
- 多執行緒之手撕執行緒池執行緒
- Java多執行緒-執行緒狀態Java執行緒
- Java多執行緒-執行緒通訊Java執行緒
- kuangshenshuo-多執行緒-執行緒池執行緒
- java多執行緒9:執行緒池Java執行緒
- java 多執行緒守護執行緒Java執行緒
- Java多執行緒(2)執行緒鎖Java執行緒
- 【java多執行緒】(二)執行緒停止Java執行緒
- 多執行緒系列之 執行緒安全執行緒
- iOS 多執行緒之執行緒安全iOS執行緒
- Java多執行緒之執行緒中止Java執行緒
- Android多執行緒之執行緒池Android執行緒