当前位置: 首页 > news >正文

iOS GCD(Grand Central Dispatch)

iOS 常用有三种线程管理方式,分别是 NSThreadGCDNSOperation,现在我们先来了解一下其中的 GCD

串行与并行针对的是任务队列,而同步与异步,针对的则是线程。

Serial Queue + Sync 序列执行+同步

Serial Queue + Async 序列执行 + 异步 (按顺序)

Concurrent Queue + Sync 并发 + 同步 (按顺序)

Concurrent Queue + Async 并发 + 异步 (真正多线程)(不按顺序)

自定义串行队列有能力启动主线程和后台线程(只能启动一个后台线程),不会发生死锁。同步任务,会自动安排在主线程执行;遇到异步任务,自动安排在后台线程执行,所以不会死锁。

DispatchWorkItem 可添加 item 到队列中

//1. 只带尾随闭包
let item1 = DispatchWorkItem {print("item1")
}//2. 指定qos(执行优先级)或flags(特殊行为标记)
let item2 = DispatchWorkItem(qos: .userInteractive, flags: .barrier) {print("item2")
}

DispatchQueue

  • Main queue (串行队列) 仅能运行在主线程上

    let mainQueue = DispatchQueue.main
    
  • Global queue(并行队列 Concurrent)

    let globalQueue = DispatchQueue.global()
    
  • Custom queue(默认串行)

    //串行队列,label名字随便取
    let serialQueue = DispatchQueue(label: "test")//并行队列
    let concurrentQueue = DispatchQueue(label: "test", attributes: .concurrent)
    

添加任务

异步

let mainQueue = DispatchQueue.main
mainQueue.async(execute: item1)let globalQueue = DispatchQueue.global()
globalQueue.async(execute: item1)let serialQueue = DispatchQueue(label: "serial")
serialQueue.async(execute: item1)let concurrentQueue = DispatchQueue(label: "concurrent", attributes: .concurrent)
concurrentQueue.async(execute: item1)

同步

let mainQueue = DispatchQueue.main
mainQueue.sync(execute: item1)    // 必定引起死锁let globalQueue = DispatchQueue.global()
globalQueue.sync(execute: item1)let serialQueue = DispatchQueue(label: "serial")
serialQueue.sync(execute: item1)let concurrentQueue = DispatchQueue(label: "concurrent", attributes: .concurrent)
concurrentQueue.sync(execute: item1)

队列死锁,而不是线程死锁。主队列添加同步任务造成死锁的根本原因:

  • 主队列只能运行在主线程。
  • 主队列没有本事开启后台线程去干别的事情。
  • 主队列一旦混入同步任务,就会跟已经存在的异步任务相互等待,导致死锁。

DispatchGroup

可把多个任务放到 group,方便管理。

当组内所有任务执行完成,GCD API 发送相应的通知。

  • notify(): 不阻塞当前线程
  • wait():阻塞当前线程

自定义串行队列一个异步或同步任务(A)嵌套另一个同步任务(B)会引起死锁。

A、B任务等效为:A1 -> B -> A2。

// 当前任务
let queue = DispatchQueue.init(label: "name")
queue.sync {// 死锁。同步要等外层执行后这里才能执行,而外层的执行需要这里先执行完。queue.sync {print(Thread.current) // 同步任务}  // 当前任务print(Thread.current)  
}

并行队列添加同步任务不会死锁,因为同步任务被安排在主线程执行,异步任务被安排在后台线程执行。

所有的同步任务最终都要安排到主线程运行,主线程运行长耗时任务会导致界面严重卡顿。

// 这两种方式都会使界面卡顿(15s)
override func viewDidAppear(_ animated: Bool) {//1. 全局队列执行同步任务DispatchQueue.global().sync {sleep(15)//当前线程休眠15秒}//2. 主队列执行异步任务DispatchQueue.main.async {sleep(15)//当前线程休眠15秒}
}

GCD 正确做法:A、B都定义成异步任务,在并行队列中嵌套异步任务,最后切换到主队列去刷新UI


let queue = DispatchQueue(label: "com.apple.request", attributes: .concurrent)//异步执行
queue.async {print("开始请求数据 \(Date())  thread: \(Thread.current)")sleep(10)//模拟网络请求print("数据请求完成 \(Date())  thread: \(Thread.current)")//异步执行queue.async {print("开始处理数据 \(Date())  thread: \(Thread.current)")sleep(5)//模拟数据处理print("数据处理完成 \(Date())  thread: \(Thread.current)")//切换到主队列,刷新UIDispatchQueue.main.async {print("UI刷新成功  \(Date())  thread: \(Thread.current)")}}
}

DispatchQueue.main 自动生成的主队列对象,可获取

DispatchQueue.global

DispatchQueue() 默认是序列队列

DispatchQueue(.concurrent) 并发队列

同步任务都会被分配到主线程。

global、自定义 serial 队列、并发队列,都有能力把异步任务分配到子线程。serial 只能开启一个子线程(做并发任务足够了)。

同队列中,同步任务会等待前方任务执行完再执行。(先来先服务)

number 是队列标识,name 是线程标识,使用 serial 安排同步任务和异步任务,会将同步的分给主线程,把异步的分给后台某个匿名线程。

let queue = DispatchQueue.init(label: "hei")
queue.async {    print(Thread.current) 
}queue.sync {queue.async {print(Thread.current)   } // 虽然比下面的 print 早,但是把这个异步任务发到另外线程这个过程需要时间。print(Thread.current) 
}queue.async {    print(Thread.current) 
} queue.sync {print(Thread.current)    
}// 结果
// <NSThread: 0x7fde7c806950>{number = 5, name = (null)}
// <_NSMainThread: 0x7fde7cb06570>{number = 1, name = main}
// <NSThread: 0x7fde7c806950>{number = 5, name = (null)}
// <NSThread: 0x7fde7c806950>{number = 5, name = (null)}
// <_NSMainThread: 0x7fde7cb06570>{number = 1, name = main}

如果 serial 队列嵌套同步任务将会死锁。

// 当前任务
let queue = DispatchQueue.init(label: "name")
queue.sync {// 死锁。同步要等外层执行后这里才能执行,而外层的执行需要这里先执行完。queue.sync {print(Thread.current) // 同步任务}  // 当前任务print(Thread.current)  
}

相关文章:

iOS GCD(Grand Central Dispatch)

iOS 常用有三种线程管理方式&#xff0c;分别是 NSThread、GCD 与 NSOperation&#xff0c;现在我们先来了解一下其中的 GCD 串行与并行针对的是任务队列&#xff0c;而同步与异步&#xff0c;针对的则是线程。 Serial Queue Sync 序列执行同步 Serial Queue Async 序列执…...

Cross-Entropy Loss(多分类损失函数)

文章目录 1. 网络输出output&#xff1a;score2. Cross-Entropy Loss(多分类损失函数) 1. 网络输出output&#xff1a;score 2. Cross-Entropy Loss(多分类损失函数) 先用softmax function把score 变成 probabilities。再用交叉熵损失函数来进行Loss的计算...

TP858 3BSE018138R1 具有高性能CPU的工业PC技术

TP858 3BSE018138R1 具有高性能CPU的工业PC技术 为了充分利用新电脑的扩展图形功能&#xff0c;如DirectX&#xff0c;Beckhoff Automation重新设计了TwinCAT automation软件套件中的Scope工具。这为TwinCAT用户在灵活的软件环境中提供了一系列令人印象深刻的测量技术。改进的…...

Observability:使用 OpenTelemetry 手动检测 .NET 应用程序

作者&#xff1a;David Hope 在快节奏的软件开发领域&#xff0c;尤其是在云原生领域&#xff0c;DevOps 和 SRE 团队日益成为应用程序稳定性和增长的重要合作伙伴。 DevOps 工程师不断优化软件交付&#xff0c;而 SRE 团队则充当应用程序可靠性、可扩展性和顶级性能的管理者。…...

生产事故:redis主从的坑

一、问题 昨天生产redis缩容&#xff0c;3主3从模式&#xff0c;重启了服务器&#xff0c;重启了redis&#xff1b; 结果今天发现生产服务报错了&#xff0c;连接不上redis。 排查发现&#xff0c;由于生产后台只配置了一个redis的ip&#xff0c;本来是主redis的ip的&#x…...

maven本地仓库有依赖包,还会远程下载的问题

maven本地仓库有依赖包&#xff0c;还会远程下载的问题 传送门...

动作捕捉系统处理单点多点丢点问题

在动作捕捉数据采集过程中&#xff0c;丢点是经常容易遇到的问题。NOKOV度量动作捕捉软件可以方便地解决丢点问题。 一、单点丢点的处理 如下图&#xff0c;已经采集了动捕数据。 查看是否有丢点&#xff0c;在形影软件左上角选择“窗口分割”&#xff0c;在下方分割出一个空…...

FIFO 位宽转换

从8位转32位 module tb_fifo();reg clk,rst; initial beginclk0;forever #4.545 clk~clk; end initial beginrst1;#9.09 rst0; endreg [31:0] cnts; always (posedge clk or posedge rst) beginif(rst)begincnts < 32d0;endelsebegincnts < cnts 1b1;end endreg […...

瑞明达:聚“追梦”之力,共圆“经济梦”

矢志不渝&#xff0c;笃行不怠&#xff0c;争当“一心一意同国行”的无悔“追梦人”。过往几年&#xff0c;国际形势风高浪急&#xff0c;国内环境复杂多变&#xff0c;在后疫情时代、经济恢复压力等多种超预期的因素冲击下&#xff0c;瑞明达团队全面贯彻落实国家发展政策&…...

UE5数字孪生制作(一) - QGIS 学习笔记

1.下载 QGIS是免费的GIS工具&#xff0c;下载地址&#xff1a; https://www.qgis.org/en/site/ 2.安装 - 转中文 按照步骤安装&#xff0c;完成后&#xff0c;在菜单 设置settings里&#xff0c;选择options&#xff0c;修改语言 确定后&#xff0c;需要重启下软件 3.学习视…...

STM32 使用HAL库,HAL_Delay()会卡死, 程序一直卡在 HAL_GetTick( ) 函数中(已解决)

今天遇到个很奇怪的问题, 不知道为什么, 单片机运行一会之后, 系统就没反应了, 经过调试发现, 系统卡在HAL_Delay()中了. 之前也遇到过这个问题后来把HAL_Delay 去掉了. 然后发现不行, 还是得有它.不然发串口数据发的太快会乱掉. 得慢点发. 然后调试到HAL_Delay()方法的内部发…...

Maven Repository使用

1.Maven Repository网站 https://mvnrepository.com/https://mvnrepository.com/ 2.查询需要的依赖 3.参考例子 <!-- https://mvnrepository.com/artifact/org.freeswitch.esl.client/org.freeswitch.esl.client --> <dependency> <groupId>org.freesw…...

智安网络|保护您的应用程序免受攻击:重要的安全强化措施

在今天的数字化时代&#xff0c;应用程序安全成为了企业和个人必须重视的重要领域。应用程序普遍存在的安全漏洞成为黑客们进行攻击的一个突破口。为了保护敏感数据和个人隐私&#xff0c;我们必须了解并实施一系列的关键措施来加固应用程序的安全性。 首先&#xff0c;一个关…...

python3.8 use async getting invalid sysntax

python3.8 use async getting invalid sysntax 加载fever-drqa时报错&#xff1a; File "/data/yangjun/fact/wikifact/scripts/search_module.py", line 2, in <module> from drq…...

Mac 解决 APP 快捷键冲突

打开 Mac 系统设置键盘->键盘快捷键->App快捷键->添加快捷键&#xff08;加号&#xff09;->标题需要和tab名称完全一致&#xff08;包括中英文、标点符号等&#xff0c;如下图&#xff09;设置快捷键即可 Reference&#xff1a; https://www.cnblogs.com/Questio…...

mysql之事务

&#xff08;一&#xff09;事务 1、事务是一种机制一个操作序列&#xff0c;包含了一组数据库的操作命令&#xff0c;所有命令都是一个整体&#xff0c;向系统提交或者撤销的操作&#xff0c;要么都执行&#xff0c;要么都不执行 2、不可分割的单位 &#xff08;二&#xf…...

组件化npm包打包和使用

背景&#xff1a;本地环境对功能组件提取&#xff0c;开发环境下通过本地路径引用&#xff0c;发布模式下走npm包引用 1、项目下新建packages/HelloWorld文件夹&#xff0c;在此文件夹下运行终端 npm init 新建packages/HelloWorld/index.vue文件 新建packages/HelloWorld/ind…...

Windows 内置Linux子系统的配置(From WSL1 to WSL2)

目录 我是如何从WSL1转到WSL2的? WSL1与WSL2的功能区别: 配置下载源 SSH配置 优雅使用windows的Linux子系统 我是如何从WSL1转到WSL2的? 第一次安装的子系统是WSL1的&#xff0c;因为不能使用systemctl &#xff0c;以及因为WSL1没有完整的Linux内核,所以使得WSL1很多命令…...

2023-11-03 android app TextView 滚动,ScrollView 之外的另外一种方法

一、布局xml文件中TextView 增加下面属性 android:maxLines "AN_INTEGER" android:scrollbars "vertical" 二、在java代码中添加下面代码&#xff0c;就可以滚动了。 m_TextView.setMovementMethod(new ScrollingMovementMethod())...

SAP 获取GOS附件清单及URL数据方法

很久没有更新了&#xff0c;断更了快两个月了&#xff0c;最近准备软考考试&#xff0c;刚考完不知道这次能不能通过 回归正题 SAP中很多业务中都是可以上传附件或者是上传URL的路径的&#xff0c;上传附件长时间会占用SAP的空间&#xff0c;使用GOS大多数都是采用上传URL的方式…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

AtCoder 第409​场初级竞赛 A~E题解

A Conflict 【题目链接】 原题链接&#xff1a;A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串&#xff0c;只有在同时为 o 时输出 Yes 并结束程序&#xff0c;否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...