iOS之线程(二)GCD
1. 概念
- GCD:Gtand Central Dispatch 中樞調(diào)度器
- GCD主要解決的是多核并行運算
- GCD是自動管理線程的生命周期的
1.1 任務(wù)
- 要執(zhí)行的操作
- 同步函數(shù):在當前線程中執(zhí)行任務(wù),不具備開啟新線程的能力,立馬在當前線程繞那個同步執(zhí)行任務(wù)
- 異步函數(shù):可以在新的線程中執(zhí)行任務(wù),具備開啟新線程的能力
1.2 隊列
- 用來存放任務(wù)
- 并發(fā)隊列(異步函數(shù)才有效)
- 串行隊列
1.3 一般使用情況
- 聲明一個任務(wù)
- 將任務(wù)添加到隊列中
- GCD會自動將隊列中的任務(wù)取出,放到對應(yīng)的線程中去
- 任務(wù)要遵循隊列的FIFO原則,先進先出,后進后出
| 異步函數(shù) | 【1】具備開啟新線程的能力【2】開啟新的線程,任務(wù)異步執(zhí)行 | 【1】具備開啟線程的能力【2】會開線程,開一條線程,隊列中的任務(wù)是按照先后順序執(zhí)行 | 【1】不會開啟新的線程 【2】串行執(zhí)行 |
| 同步函數(shù) | 【1】不會開啟新的線程【2】串行執(zhí)行任務(wù) | 【1】不會開啟新的線程【2】串行執(zhí)行任務(wù) | 【1】如果在主線程中執(zhí)行會發(fā)生死鎖【2】在子線程可以 |
2. 異步函數(shù)并發(fā)隊列
- 異步函數(shù) :具備開啟新線程的能力
- 異步函數(shù) + 并發(fā)隊列 ->開新線程,隊列中的任務(wù)是異步執(zhí)行
注意: 一個隊列中可以.可以添加多個任務(wù),CGD開啟線程是不受控制的,不是說有多少個任務(wù)就開啟多少條線程,具體的是系統(tǒng)內(nèi)部決定的
3. 異步函數(shù) 串行隊列
- 異步函數(shù) :具備開啟新線程的能力
- 異步函數(shù) + 串行隊列: 會開線程,開一條線程,隊列中的任務(wù)是按照先后順序執(zhí)行
其實上面的創(chuàng)建的并發(fā)隊列,可以換成系統(tǒng)的全局并發(fā)隊列,區(qū)別:上面是自己手動創(chuàng)建的并發(fā)隊列,下面是獲取系統(tǒng)的
//獲取全局并發(fā)隊列dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);4. 同步函數(shù)+并發(fā)隊列
- 同步函數(shù):不具備開啟新線程的能力
- 同步函數(shù)+并發(fā)隊列:不會開啟子線程,串行執(zhí)行任務(wù)
5. 同步函數(shù)+串行隊列
- 同步函數(shù):不具備開啟新線程的能力
- 同步函數(shù)+串行隊列:不會開啟新的線程
6.主隊列
- 主隊列是GCD自帶的一種比較特殊的串行隊列
- 在主隊列中的任務(wù),都是在主線程中執(zhí)行的
- 獲取主隊列 dispatch_get_main_queue()
6.1異步函數(shù)+主隊列
- 不會開啟子線程
6.2 同步函數(shù) + 主隊列
- 同步函數(shù):不具備開啟新線程能力,立馬執(zhí)行,如果這個任務(wù)沒有執(zhí)行完,不會執(zhí)行下一個任務(wù)
- 產(chǎn)生:死鎖
6.3 線程產(chǎn)生死鎖
造成死鎖的條件: 使用同步sync函數(shù) 往當前 串行( SERIAL)隊列 添加任務(wù), 會卡住當前任務(wù)造成死鎖
線程死鎖
dispatch_sync同步:立馬執(zhí)行當前線程中的任務(wù),執(zhí)行完畢才能繼續(xù)往下執(zhí)行
FIFO原則: 先進的先出
意思就是: 整個函數(shù) viewdidload執(zhí)行完,打印333,才可以執(zhí)行 同步的任務(wù) 打印222, 由于同步函數(shù)sync 要立馬執(zhí)行當前任務(wù),打印222,才可以執(zhí)行打印333,所以會產(chǎn)生死鎖
原因:
1,創(chuàng)建了一個 子線程
2.隊列0 和 隊列1 都在 子線程中執(zhí)行
3.由于隊列0 執(zhí)行到 打印執(zhí)行任務(wù)2時,遇到 同步函數(shù),要立馬執(zhí)行函數(shù)內(nèi) 隊列1的任務(wù), 此時隊列0的打印任務(wù)4 還沒有執(zhí)行完, 所以要等打印任務(wù)4執(zhí)行完,才可以執(zhí)行 同步函數(shù) 隊列1,造成了線程死鎖
7.線程之間的通信
- 只要是主隊列一定是在主線程執(zhí)行的
8. GCD任務(wù)加強
//任務(wù)加強 - (void)demo1{//獲取并發(fā)隊列dispatch_queue_t queue = dispatch_get_global_queue(0, 0);//包裝void(^task)(void) = ^{dispatch_sync(queue, ^{NSLog(@"1111---同步--%@",[NSThread currentThread]);});dispatch_async(queue, ^{NSLog(@"2222---異步步--%@",[NSThread currentThread]);});dispatch_async(queue, ^{NSLog(@"33333---異步步--%@",[NSThread currentThread]);});};//執(zhí)行任務(wù)dispatch_async(queue, task);}9.柵欄函數(shù)
柵欄函數(shù)是:保證次函數(shù)前面的執(zhí)行完,然后執(zhí)行自己的柵欄函數(shù),然后在執(zhí)行 函數(shù)后面的線程
注意:
1.全局并發(fā)隊列,對柵欄函數(shù)沒有作用
2.使用柵欄函數(shù),必須是自己手動創(chuàng)建的并發(fā)隊列
10.同時執(zhí)行函數(shù) apply
我們知道 for循環(huán)是 執(zhí)行一次循環(huán),在執(zhí)行下一次循環(huán)
有時我們在開發(fā)會遇到,多個任務(wù)同時執(zhí)行的問題,比如:同時copy圖片到另外一個文件夾中,此時就會用到 apply同時執(zhí)行函數(shù)
11.CGD 隊列組 - group
- (void)demo1{//創(chuàng)建隊列dispatch_queue_t queue = dispatch_get_global_queue(0, 0);//創(chuàng)建任務(wù)組dispatch_group_t group = dispatch_group_create();//異步dispatch_group_async(group, queue, ^{NSLog(@"AAAA");});//異步dispatch_group_async(group, queue, ^{NSLog(@"bbbb");});//異步dispatch_group_async(group, queue, ^{NSLog(@"CCCC");});// 就是保證上面的3個任務(wù) 執(zhí)行完畢 之后才執(zhí)行 dispatch_group_notify//這個任務(wù)組完成的通知dispatch_group_notify(group, queue, ^{NSLog(@"所有的任務(wù)完成");});NSLog(@"11111"); }12 .常用的函數(shù)
12.1一次性執(zhí)行函數(shù)
//MARK:---一次性執(zhí)行函數(shù) - (void)testOnce{static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{NSLog(@"執(zhí)行一次就b在執(zhí)行了");}); }12.2 常用的代碼執(zhí)行 延遲操作
//MARK:---延遲執(zhí)行 - (void)testDiplay{//延遲2l秒執(zhí)行[self performSelector:@selector(run) withObject:nil afterDelay:2.0];//延遲3秒執(zhí)行[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(run) userInfo:nil repeats:NO];dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(4.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{NSLog(@"延遲4秒執(zhí)行");});}- (void)run {NSLog(@"奔跑"); }總結(jié)
以上是生活随笔為你收集整理的iOS之线程(二)GCD的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分享几个路由器设置小技巧,总有用得到的一
- 下一篇: 区块链是大数据生态圈技术之一_区块链技术