日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

iOS之线程(二)GCD

發(fā)布時間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS之线程(二)GCD 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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原則,先進先出,后進后出
使用并發(fā)隊列串行隊列主隊列
異步函數(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í)行
/*參數(shù)一: C語言的字符串,標識符用來區(qū)分隊列參數(shù)二: 隊列的類型DISPATCH_QUEUE_CONCURRENT 并發(fā)隊列DISPATCH_QUEUE_SERIAL 串行隊列*///創(chuàng)建一個隊列dispatch_queue_t queue = dispatch_queue_create("www.cc.com", DISPATCH_QUEUE_CONCURRENT);//聲明任務(wù)//第一個參數(shù):隊列//要執(zhí)行的任務(wù)// dispatch_async(dispatch_queue_t queue, dispatch_block_t block);dispatch_async(queue, ^{NSLog(@"111111,--%@",[NSThread currentThread]);});

注意: 一個隊列中可以.可以添加多個任務(wù),CGD開啟線程是不受控制的,不是說有多少個任務(wù)就開啟多少條線程,具體的是系統(tǒng)內(nèi)部決定的

3. 異步函數(shù) 串行隊列

  • 異步函數(shù) :具備開啟新線程的能力
  • 異步函數(shù) + 串行隊列: 會開線程,開一條線程,隊列中的任務(wù)是按照先后順序執(zhí)行
//創(chuàng)建串行隊列dispatch_queue_t queue = dispatch_queue_create("cc", DISPATCH_QUEUE_SERIAL);//創(chuàng)建異步函數(shù)任務(wù)dispatch_async(queue, ^{NSLog(@"2222222--%@",[NSThread currentThread]);});dispatch_async(queue, ^{NSLog(@"3333--%@",[NSThread currentThread]);});

其實上面的創(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ù)
//創(chuàng)建隊列dispatch_queue_t queue = dispatch_queue_create("hhh", DISPATCH_QUEUE_CONCURRENT);//創(chuàng)建任務(wù)//同步函數(shù)dispatch_sync(queue, ^{NSLog(@"999--%@",[NSThread currentThread]);});// 999--<NSThread: 0x60000155a240>{number = 1, name = main}

5. 同步函數(shù)+串行隊列

  • 同步函數(shù):不具備開啟新線程的能力
  • 同步函數(shù)+串行隊列:不會開啟新的線程
//創(chuàng)建隊列dispatch_queue_t queue = dispatch_queue_create("kkk", DISPATCH_QUEUE_SERIAL);//同步函數(shù)dispatch_sync(queue, ^{NSLog(@"%@",[NSThread currentThread]);});

6.主隊列

  • 主隊列是GCD自帶的一種比較特殊的串行隊列
  • 在主隊列中的任務(wù),都是在主線程中執(zhí)行的
  • 獲取主隊列 dispatch_get_main_queue()
6.1異步函數(shù)+主隊列
  • 不會開啟子線程
// 獲取主隊列dispatch_queue_t queue = dispatch_get_main_queue();//異步函數(shù)執(zhí)行dispatch_async(queue, ^{NSLog(@"%@",[NSThread currentThread]);});
6.2 同步函數(shù) + 主隊列
  • 同步函數(shù):不具備開啟新線程能力,立馬執(zhí)行,如果這個任務(wù)沒有執(zhí)行完,不會執(zhí)行下一個任務(wù)
  • 產(chǎn)生:死鎖
// 獲取主隊列dispatch_queue_t queue = dispatch_get_main_queue();//同步函數(shù)執(zhí)行dispatch_sync(queue, ^{NSLog(@"%@",[NSThread currentThread]);});
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)生死鎖

//MARK:---線程產(chǎn)生死鎖 - (void)GCDLock1{//原則: 同步線程 要立馬執(zhí)行// FIFO:先進先出的原則,那個任務(wù) 先進來 馬哥現(xiàn)任縣執(zhí)行//GCDLock1 在主隊列中,要先執(zhí)行完 這個線程//dispatch_sync 隊列要立馬在當前線程執(zhí)行, 所以會產(chǎn)生死鎖//打印人3333 要先執(zhí)行完,才會執(zhí)行 打印2222,//然而 打印任務(wù)2222 要立馬執(zhí)行完,才會執(zhí)行打印任務(wù)3333NSLog(@"11111");dispatch_queue_t que = dispatch_get_main_queue();dispatch_sync(que, ^{NSLog(@"22222");});NSLog(@"333333");}

原因:
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,造成了線程死鎖

// MARK:---會產(chǎn)生死鎖2 - (void)GCDLock3 {//會產(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,造成了線程死鎖NSLog(@"執(zhí)行任務(wù)1");//DISPATCH_QUEUE_SERIAL 串行隊列dispatch_queue_t que = dispatch_queue_create("myque", DISPATCH_QUEUE_SERIAL);dispatch_async(que, ^{ // 線程 隊列0NSLog(@"執(zhí)行任務(wù)2");dispatch_sync(que, ^{ //線程 隊列1NSLog(@"執(zhí)行任務(wù)3");});NSLog(@"執(zhí)行任務(wù)4");});NSLog(@"執(zhí)行任務(wù)5"); }

7.線程之間的通信

  • 只要是主隊列一定是在主線程執(zhí)行的
- (void)setup7 {//1.獲取全局并發(fā)隊列dispatch_queue_t globalQue = dispatch_get_global_queue(0, 0);//異步函數(shù)執(zhí)行dispatch_async(globalQue, ^{//URLNSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559637616849&di=ac9047efc5fb0dbe9eb8d55e321ac4a5&imgtype=0&src=http%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FzfDDxwQnD2Qib4s4tN6tVjeD9TXIedpicIZvKjL1u6MfRicUeAx9t31HLBrh11bfxhbiakH0te22TicfmCZgbErp3Gw%2F640%3Fwx_fmt%3Djpeg"];//回去二進制數(shù)據(jù)NSData *data = [NSData dataWithContentsOfURL:url];UIImage *image = [UIImage imageWithData:data];//g回到主隊列s刷新界面dispatch_async(dispatch_get_main_queue(), ^{NSLog(@"回到主隊列");self.imgageView.image = image;});});}

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ā)隊列

//MARK:---柵欄函數(shù)- (void)testBary {//群居并發(fā)隊列 // dispatch_queue_t que = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//自己手動穿件的隊列dispatch_queue_t que = dispatch_queue_create("cc", DISPATCH_QUEUE_CONCURRENT);dispatch_async(que, ^{NSLog(@"---%@---1----",[NSThread currentThread]);});dispatch_async(que, ^{NSLog(@"---%@---2----",[NSThread currentThread]);});dispatch_barrier_async(que, ^{NSLog(@"-柵欄函數(shù)--%@-------",[NSThread currentThread]);});dispatch_async(que, ^{NSLog(@"---%@---3----",[NSThread currentThread]);});dispatch_async(que, ^{NSLog(@"---%@---4----",[NSThread currentThread]);});}

10.同時執(zhí)行函數(shù) apply

我們知道 for循環(huán)是 執(zhí)行一次循環(huán),在執(zhí)行下一次循環(huán)
有時我們在開發(fā)會遇到,多個任務(wù)同時執(zhí)行的問題,比如:同時copy圖片到另外一個文件夾中,此時就會用到 apply同時執(zhí)行函數(shù)

- (void)viewDidLoad {[super viewDidLoad];// DISPATCH_QUEUE_PRIORITY_DEFAULT 默認隊列dispatch_queue_t que = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//同時執(zhí)行 并發(fā)隊列 ,執(zhí)行10不同的任務(wù)dispatch_apply(10, que, ^(size_t index) {NSLog(@"--%zd--%@---",index,[NSThread currentThread]);});}

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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。