OC 知识 多线程 GCD(源码)

news2024/11/25 4:46:40

一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希望未来技术之巅上有你们也有我。

通过下面的两个方法可以证明:

代码如下(示例):

提示:这里对文章进行总结:

前言

正题

1.什么是线程

2.什么是串行队列和异步队列

串行队列或者异步队列只会控制任务是否按顺序执行.
串行队列是按顺序执行的.
异步队列是不顺序执行的

通过下面的两个方法可以证明:

串行队列-异步线程

- (void)gcdDemo2 {
  //创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("itcast", DISPATCH_QUEUE_SERIAL);
    
    for (int i = 0; i < 200; ++i) {
        dispatch_async(queue, ^{
            // 异步执行
            NSLog(@"%@ - %d",[NSThread currentThread],i);
        });
    }
}

答案:按顺序执行,只开一条线程,为什么?

因为在一个串行的队列里面添加了200个任务,每个任务都是在串行中需要排队执行,在这个串行队列里面,当前的任务没有执行完毕,下一个任务是不会开始执行的.即使现在开启了有多个异步线程number3,number4,number5…空闲着,在串行队列里面,也不会把任务放到number3,number4,number5里面去执行,实际也不会有number3,number4,number5等多个异步线程在空闲去浪费资源,因为线程空闲会被收回到可用线程池,但主线程是不会被收回.

在这里插入图片描述

在这里插入图片描述

并发队列-异步线程

答案:不按顺序执行,开多条线程

- (void)gcdDemo2 {
  //创建一个并发队列
    dispatch_queue_t queue = dispatch_queue_create("itcast", DISPATCH_QUEUE_CONCURRENT);
    
    for (int i = 0; i < 200; ++i) {
        dispatch_async(queue, ^{
            // 异步执行
            NSLog(@"%@ - %d",[NSThread currentThread],i);
        });
    }
}

在这里插入图片描述

在这里插入图片描述

3.什么同步线程和异步线程

同步线程和异步线程只会控制是否开启线程
同步线程是不开线程,在主线程中执行
异步线程是开线程,不在主线程中执行

通过下面的两个方法可以证明:

有开启线程

//创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("itcast", DISPATCH_QUEUE_SERIAL);
// 异步
dispatch_async(queue, ^{
    NSLog(@"%@",[NSThread currentThread]);
});

开启了异步线程,证明有开线程
在这里插入图片描述

没有开启线程

//创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("itcast", DISPATCH_QUEUE_SERIAL);
// 同步
dispatch_sync(queue, ^{
    NSLog(@"%@",[NSThread currentThread]);
});

程序本身在主线程里面运行
在这里插入图片描述

4.开启一个串行队列在异步线程中执行

OC-串行队列在异步线程中执行

按顺序执行,可以开线程

- (void)gcdDemo {
    //创建一个串行队列
    dispatch_queue_t queue = dispatch_queue_create("itcast", DISPATCH_QUEUE_SERIAL);
    for (int i = 0; i < 100; i++) {
        // 异步
        dispatch_async(queue, ^{
            NSLog(@"%@, %d",[NSThread currentThread], i);
        });
    }
}

在这里插入图片描述

5.开启一个串行队列在同步线程中执行

OC- 串行队列在同步线程中执行

肯按顺序执行,不开线程

//创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("itcast", DISPATCH_QUEUE_SERIAL);
for (int i = 0; i < 100; i++) {
    // 异步
    dispatch_sync(queue, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });
}

在这里插入图片描述

6.开启一个并发队列在异步线程中执行

OC-并发队列在异步线程中执行
不按顺序执行,可以开线程

- (void)gcdDemo {
    //创建一个并发队列
    dispatch_queue_t queue = dispatch_queue_create("itcast", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 100; i++) {
        // 异步
        dispatch_async(queue, ^{
            NSLog(@"%@",[NSThread currentThread]);
        });
    }
}

在这里插入图片描述

7.开启一个并发队列在同步线程中执行

OC- 并发队列在同步线程中执行
不按顺序执行,不开线程

- (void)gcdDemo {
    // 1. 创建一个并发队列
    // DISPATCH_QUEUE_CONCURRENT 用于创建并发队列
    dispatch_queue_t queue = dispatch_queue_create("itcast", DISPATCH_QUEUE_CONCURRENT);

    for (int i = 0; i < 100; i++) {
        // 同步
        dispatch_sync(queue, ^{
            NSLog(@"%@",[NSThread currentThread]);
        });
    }
}

在这里插入图片描述

8.开多少条线程又谁来决定?

开多少硬件或者软件决定 如果开启并发队列-异步线程执行200个任务,开多少条线程根据任务本身来决定的,例如,任务1下载一张图片,任务2下载一场电影,如果执行快的任务可以重新利用旧的线程,如果任务大就会开新的线程.

9.什么是主队列

OC- 主队列-示例代码
专门处理主线程中的任务,就是主队列,按顺序执行,先进先出.

添加到主队列中的任务是在主线程有空的时候才执行.

证明:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self gcdDemo];
    NSLog(@"end");
}

-(void)gcdDemo {
    // 1. 获取主队列
    dispatch_queue_t queue = dispatch_get_main_queue();
    
    // 异步是可以先往下执行代码,再回来执行
    dispatch_async(queue, ^{
        NSLog(@"%@",[NSThread currentThread]);
    });
}

在这里插入图片描述
上面的代码打印了end才去执行主队列的任务.说明等主队列有空的才去执行.

10.同步线程和异步线程里面执行方法的顺序关系

在一个方法里面异步线程里面的函数跟方法外面的函数是不按顺序执行的
在这里插入图片描述
在一个方法里面同步线程里面的函数跟方法外面的函数是按顺序执行的
在这里插入图片描述

11.死锁

产生死锁的原因是因为主队列的任务必须有空闲才执行,也就是执行函数1才去执行函数2,但是现在主队列必须是按顺序执行的,也就是执行函数2才去执行函数1.这样产生了矛盾.
在这里插入图片描述
如果非要使用主队列去执行的话解决办法看下面的代码:
在这里插入图片描述
在这里插入图片描述

12.同步的作用

保证先执行某些程序再去执行别的程序.
例如肯定先登录之后才能下载.
在这里插入图片描述

13.全局队列(跟并发一样,可以开多小线程)

OC- 全局队列-示例代码

- (void)gcdDemo {
    //创建全局队列
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    //异步线程中执行
    for (int i = 0; i < 200; i++) {
        dispatch_async(queue, ^{
            NSLog(@"%@ - %d",[NSThread currentThread], i);
        });
    }
}

在这里插入图片描述
在这里插入图片描述

重点,主队列执行耗时操作完回到主线程刷新UI

我们一般会在主队列中执行一下好事操作的代码,下载图片,然后下载完成之后回到主线程里面刷新UI
在这里插入图片描述

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    NSLog(@"耗时操作");
    
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"回到主线程刷新UI");
    });
});

14.barrier 异步(少用)

注意barrier,一定要使用异步,如果同步会产生死锁,因为barrier的代码是等待异步执行完才去执行barrier,如果使用同步,同步要barrier执行完才往下走,barrier也等同步执行完才往下走,造成互相等待,产生死锁

主要用于多个异步操作完成之后,统一对非线程安全的对象进行更新

看下面的代码,代码在下载(运行)过程中会然后不停的点击会出现奔溃的可能
在这里插入图片描述
也就是说这样把图片保存进去数组是不安全的,应该放到安全的地方去执行.为什么不安全呢?因为在异步下载图片的时候,把下载完的图片直接保存进去数据,也是在异步线程里面完成,如果点击屏幕的操作产生的时间差异,可以异步刚好下载两张图片保存在数组的同一个地方.

解决办法就是把图片下载完成的操作代码保存起来,等所有图片下载完成之后,在统一的线程里面保存图片

在这里插入图片描述
在这里插入图片描述
其实可以回到主线程保存图片

15.GCD延时操作的方法

OC- GCD延时-示例代码
参数一: 什么时候开始算起 DISPATCH_TIME_NOW 现在
参数二: 几秒钟之后执行代码。0.3秒后 (NSEC_PER_SEC)10亿纳秒 = 1秒
参数三: dispatch_get_main_queue()。延时之后在那个队列中执行 主队列,如果想在其他线程中执行可以传递其他的子线程进去

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    //dosoming
});

参数三: dispatch_get_main_queue()。延时之后在那个队列中执行 主队列,如果想在其他线程中执行可以传递其他的子线程进去,例如看下面的代码

在这里插入图片描述

16.调度组

OC- 调度组-示例代码

假如做电商的项目里面首页加载数据,首先请求3个接口,等数据全部回来之后才去刷新UI,就可以使用下面的方法去做
在这里插入图片描述

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];

}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self gcdDemo2];
}

- (void)gcdDemo2 {
    // 先创建一个组
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    // 调度组
    dispatch_group_async(group, queue, ^{
        NSLog(@"下载文件A");
    });
    
    dispatch_group_async(group, queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"下载文件B");
    });
    
    dispatch_group_async(group, queue, ^{
        NSLog(@"下载文件C");
        
    });
    
    
    // 注册通知
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"文件下载完成,刷新UI");
    });
    NSLog(@"end");
}
@end

在这里插入图片描述

主要的工作原理;当开启异步线程去做很多个任务的时候,没去做一个任务都会把它放到组里面去,然后没放一个任务都必须等待完成,移除组,如果没有移除,就等于没有完成,就不会有通知,添加多少个进组,就有多少个等待移除.所以只有全部移除就会发送通知.这样可以回到主线程刷新UI

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/614655.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity与Android交互(2)——常用交互方式

常用AndroidJavaClass/AndroidJavaObject实现C#调用Java代码&#xff0c;常用UnitySendMessage实现Java调用C#代码。 【调用代码示例】 Java代码为&#xff1a; package com.test.addtest;import com.unity3d.player.UnityPlayer;public class JavaTestClass {public static…

BM1684X移植自写算法记录

移植步骤------------------------------------------------------------------------ 首先搭建好自己的网络模型&#xff0c;并导出为onnx格式--具体可以参照--> https://github.com/warren-wzw/MNIST-pytorch.git 将onnx模型使用tpu-mlir工具转化为bmodel格式--具体可以…

2.3 TensorRT基于Entropy的校准

tensorRT的Entropy Calibration的伪代码&#xff0c;具体流程如下&#xff1a; for循环&#xff1a;遍历所有可能的分割点&#xff0c;从128到2048reference_distribution_P&#xff1a;将原始直方图bins按照当前分割点i进行切割&#xff0c;得到左侧的i个bin。outliers_count…

构建新型智能化智慧档案馆十防一体化解决技术方案

HONSOR现代化智慧档案馆智慧档案库房自动化温湿度环境安全监控系统方案【推介】 目前&#xff0c;我国档案正处于现代化科技飞升的起点&#xff0c;以物联网、大数据、智能化、云计算等为标志的网络充斥到社会生活、生产的各个角落。在我国&#xff0c;档案馆产生与发展经历了一…

为了搞懂ERP,我连问 ChatGPT 30个问题,通透!

我对ERP有很多的疑问&#xff0c;这次向ChatGPT请教&#xff0c;连问30个问题&#xff0c;瞬间觉得通透了很多&#xff0c;以下是我的问题和ChatGPT的回复&#xff0c;分为概念篇、架构篇和生态篇三部分&#xff0c;希望能带给你新的启示。 一、概念篇 1、ERP是什么&#xff1f…

图论与算法(5)图的广度优先遍历应用

1. 广度优先遍历 1.1 树的广度优先遍历 树的广度优先遍历&#xff08;Breadth-First Traversal&#xff09;&#xff0c;也称为层次遍历&#xff0c;是一种按层次顺序逐级访问树节点的遍历方式。在广度优先遍历中&#xff0c;先访问树的根节点&#xff0c;然后按照从上到下、…

高频面试八股文用法篇(二) hive中几种排序类型区别

目录 排序函数 1、order by 2、sort by 3、distribute by 4、cluster by 总结 排序类型 1、order by order by是与关系型数据库的用法是一样的。select * from emp order by empno desc; 针对全局数据进行排序&#xff0c;所以最终只会有1个reduce&#xff0c;因…

开源 Golang 微服务入门一: HTTP 框架 Hertz

前言 从本篇笔记开始将介绍 Go 框架三件套&#xff08;Web / RPC / ORM&#xff09;&#xff0c;框架的学习有助于后续课程的学习以及大项目的完成。本文主要介绍字节跳动的开源 Golang 微服务 HTTP 框架 Hertz。先了解一下三件套的相关基本知识&#xff0c;做一下铺垫&#x…

ArgoCD(二)--部署

3.2 ArgoCD部署 ArgoCD部署官网&#xff1a;https://argo-cd.readthedocs.io/en/stable/getting_started/ ArgoCD有两种部署方式&#xff1a;多租户部署和核心化部署&#xff1a; 多租户 常用于多个应用程序开发团队提供服务&#xff0c;并由平台团队维护的场景&#xff1b; …

BPMN模拟动画执行流程

目录 第一步&#xff1a;构建BPMN图 第二步&#xff1a;开启模拟 第三步&#xff1a;执行模拟 第四步&#xff1a;监听模拟 第一步&#xff1a;构建BPMN图 通过id标记&#xff0c;每一个流程 第二步&#xff1a;开启模拟 BPMN官方提供了各种各样的模块&#xff0c;比如执行…

修改linux ssh 22 端口

1、找到 sshd 的配置文件&#xff0c;增加一行 Port 32586 ,默认是 22 端口&#xff0c;记得&#xff0c;先不要把 22 端口的这一行删除&#xff0c;或者注释&#xff0c;因为我们要先验证一下&#xff0c;我们修改后的端口是否可以使用&#xff0c;都ok后&#xff0c;再把 22 …

精通Java数组的艺术:从初学者到高手的进阶之路(二)

⭐ 多维数组⭐ 数组存储表格数据⭐ Comparable 接口 ⭐ 多维数组 多维数组可以看成以数组为元素的数组。可以有二维、三维、甚至更多维数组&#xff0c;但是实际开发中用的非常少。最多到二维数组。 【eg】二维数组的声明 public class Test {public static void main(Strin…

一起看 I/O | Wear OS 更新一览

作者 / Android 开发者关系工程师 Kseniia Shumelchyk 随着 Wear OS 平台的不断发展&#xff0c;我们很高兴与您分享一些最新的功能和改进&#xff0c;以帮助您为用户打造富有吸引力的创新体验。 Peloton 和 Todoist 等合作伙伴一直以来都针对 Wear OS 打造卓越体验&#xff0c…

Android自定义一个车牌字母选择键盘

在一般和车相关的应用&#xff0c;难免会和车牌打交道&#xff0c;组成车牌的要素&#xff0c;国内无非就是省份简称地区代码英文或者数字组成&#xff0c;比如京A12345&#xff0c;在需要输入车牌的功能上&#xff0c;就需要有省份简称键盘和英文数字键盘了&#xff0c;在上篇…

深度学习(自编码器)

深度学习目录 自适应线性单元 (Widrow and Hoff, 1960)神经认知机 (Fukushima, 1980)GPU-加速 卷积网络 (Chellapilla et al., 2006)深度玻尔兹曼机 (Salakhutdinov and Hinton, 2009a)无监督卷积网络 (Jarrett et al., 2009b)GPU-加速 多层感知机 (Ciresan et al., 2010)分布…

人工影响天气期末复习笔记

&#xff08;一&#xff09;什么是人工影响天气 利用自然云微物理不稳定性&#xff0c;通过一定的技术方法改变云的微结构&#xff0c;从而改变云降水的发展过程&#xff0c;从而达到增加降水&#xff0c;防雹&#xff0c;消云雾等目的 &#xff08;二&#xff09;为什么要人工…

【历史上的今天】6 月 6 日:世界 IPv6 启动纪念日;《俄罗斯方块》发布;小红书诞生

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 6 月 6 日&#xff0c;在 2019 年的今天&#xff0c;工信部正式发放 5G 牌照。这一天&#xff0c;有四家企业被颁发了基础电信业务经营许可证&#xff0c;从此…

社区团购系统源码后台解析

近年来&#xff0c;随着购物方式的改变&#xff0c;社区团购可以说是越来越受关注了&#xff0c;大家应该对社区团购多多少少有一些认知&#xff0c;其实社区团购这样的商业模式拥有强大的赚钱的潜力&#xff0c;主要就是因为它的运营成本低&#xff0c;而且上手也不需要很复杂…

FPGA设计的指导性原则 (四)

在FPGA Express/FPGA Compiler II中,用鼠标右键单击编译后的芯片图标, 在弹出的命令对话框中选择“Edit Constraints”命令编辑综合约束文件(扩展 名为CTL),选择端口(Ports)选项卡,指定所需信号的全局时钟域为 “DONT USE”。图22所示为在FPGA Express综合约束编辑器中…

私有化部署低代码开发工具:jvs-rules 规则引擎决策流参数说明

JVS规则引擎决策调用 通过决策流水号查询入参变量 [请求参数]决策流 ​ GET/mgr/risk//test/parameter/flow/{no} 请求数据类型 application/x-www-form-urlencoded 响应数据类型 [ "*/*" ] 请求参数 参数名称 参数说明 请求类型 是否必须 数据类型 sch…