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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

iOS之线程(二)GCD

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

1. 概念

  • GCD:Gtand Central Dispatch 中樞調度器
  • GCD主要解決的是多核并行運算
  • GCD是自動管理線程的生命周期的
1.1 任務
  • 要執行的操作
  • 同步函數:在當前線程中執行任務,不具備開啟新線程的能力,立馬在當前線程繞那個同步執行任務
  • 異步函數:可以在新的線程中執行任務,具備開啟新線程的能力
1.2 隊列
  • 用來存放任務
  • 并發隊列(異步函數才有效)
  • 串行隊列
1.3 一般使用情況
  • 聲明一個任務
  • 將任務添加到隊列中
    • GCD會自動將隊列中的任務取出,放到對應的線程中去
    • 任務要遵循隊列的FIFO原則,先進先出,后進后出
使用并發隊列串行隊列主隊列
異步函數【1】具備開啟新線程的能力【2】開啟新的線程,任務異步執行【1】具備開啟線程的能力【2】會開線程,開一條線程,隊列中的任務是按照先后順序執行【1】不會開啟新的線程 【2】串行執行
同步函數【1】不會開啟新的線程【2】串行執行任務【1】不會開啟新的線程【2】串行執行任務【1】如果在主線程中執行會發生死鎖【2】在子線程可以

2. 異步函數并發隊列

  • 異步函數 :具備開啟新線程的能力
  • 異步函數 + 并發隊列 ->開新線程,隊列中的任務是異步執行
/*參數一: C語言的字符串,標識符用來區分隊列參數二: 隊列的類型DISPATCH_QUEUE_CONCURRENT 并發隊列DISPATCH_QUEUE_SERIAL 串行隊列*///創建一個隊列dispatch_queue_t queue = dispatch_queue_create("www.cc.com", DISPATCH_QUEUE_CONCURRENT);//聲明任務//第一個參數:隊列//要執行的任務// dispatch_async(dispatch_queue_t queue, dispatch_block_t block);dispatch_async(queue, ^{NSLog(@"111111,--%@",[NSThread currentThread]);});

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

3. 異步函數 串行隊列

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

其實上面的創建的并發隊列,可以換成系統的全局并發隊列,區別:上面是自己手動創建的并發隊列,下面是獲取系統的

//獲取全局并發隊列dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

4. 同步函數+并發隊列

  • 同步函數:不具備開啟新線程的能力
  • 同步函數+并發隊列:不會開啟子線程,串行執行任務
//創建隊列dispatch_queue_t queue = dispatch_queue_create("hhh", DISPATCH_QUEUE_CONCURRENT);//創建任務//同步函數dispatch_sync(queue, ^{NSLog(@"999--%@",[NSThread currentThread]);});// 999--<NSThread: 0x60000155a240>{number = 1, name = main}

5. 同步函數+串行隊列

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

6.主隊列

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

造成死鎖的條件: 使用同步sync函數 往當前 串行( SERIAL)隊列 添加任務, 會卡住當前任務造成死鎖

線程死鎖
dispatch_sync同步:立馬執行當前線程中的任務,執行完畢才能繼續往下執行
FIFO原則: 先進的先出

意思就是: 整個函數 viewdidload執行完,打印333,才可以執行 同步的任務 打印222, 由于同步函數sync 要立馬執行當前任務,打印222,才可以執行打印333,所以會產生死鎖

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

原因:
1,創建了一個 子線程
2.隊列0 和 隊列1 都在 子線程中執行
3.由于隊列0 執行到 打印執行任務2時,遇到 同步函數,要立馬執行函數內 隊列1的任務, 此時隊列0的打印任務4 還沒有執行完, 所以要等打印任務4執行完,才可以執行 同步函數 隊列1,造成了線程死鎖

// MARK:---會產生死鎖2 - (void)GCDLock3 {//會產生死鎖// 原因: 1,創建了一個 子線程// 2.隊列0 和 隊列1 都在 子線程中執行// 3.由于隊列0 執行到 打印執行任務2時,遇到 同步函數,要立馬執行函數內 隊列1的任務, 此時隊列0的打印任務4 還沒有執行完, 所以要等打印任務4執行完,才可以執行 同步函數 隊列1,造成了線程死鎖NSLog(@"執行任務1");//DISPATCH_QUEUE_SERIAL 串行隊列dispatch_queue_t que = dispatch_queue_create("myque", DISPATCH_QUEUE_SERIAL);dispatch_async(que, ^{ // 線程 隊列0NSLog(@"執行任務2");dispatch_sync(que, ^{ //線程 隊列1NSLog(@"執行任務3");});NSLog(@"執行任務4");});NSLog(@"執行任務5"); }

7.線程之間的通信

  • 只要是主隊列一定是在主線程執行的
- (void)setup7 {//1.獲取全局并發隊列dispatch_queue_t globalQue = dispatch_get_global_queue(0, 0);//異步函數執行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"];//回去二進制數據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任務加強

//任務加強 - (void)demo1{//獲取并發隊列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]);});};//執行任務dispatch_async(queue, task);}

9.柵欄函數

柵欄函數是:保證次函數前面的執行完,然后執行自己的柵欄函數,然后在執行 函數后面的線程
注意:
1.全局并發隊列,對柵欄函數沒有作用
2.使用柵欄函數,必須是自己手動創建的并發隊列

//MARK:---柵欄函數- (void)testBary {//群居并發隊列 // 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(@"-柵欄函數--%@-------",[NSThread currentThread]);});dispatch_async(que, ^{NSLog(@"---%@---3----",[NSThread currentThread]);});dispatch_async(que, ^{NSLog(@"---%@---4----",[NSThread currentThread]);});}

10.同時執行函數 apply

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

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

11.CGD 隊列組 - group

- (void)demo1{//創建隊列dispatch_queue_t queue = dispatch_get_global_queue(0, 0);//創建任務組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個任務 執行完畢 之后才執行 dispatch_group_notify//這個任務組完成的通知dispatch_group_notify(group, queue, ^{NSLog(@"所有的任務完成");});NSLog(@"11111"); }

12 .常用的函數

12.1一次性執行函數
//MARK:---一次性執行函數 - (void)testOnce{static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{NSLog(@"執行一次就b在執行了");}); }

12.2 常用的代碼執行 延遲操作

//MARK:---延遲執行 - (void)testDiplay{//延遲2l秒執行[self performSelector:@selector(run) withObject:nil afterDelay:2.0];//延遲3秒執行[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秒執行");});}- (void)run {NSLog(@"奔跑"); }

總結

以上是生活随笔為你收集整理的iOS之线程(二)GCD的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。