news 2026/8/24 3:00:03

接上篇ios

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
接上篇ios

iOS端对应关系

Python:

  1. ThreadPoolExecutor(max_workers)→ 管控线程池内部任务,只限制本池,靠worker线程数量做并发控制
  2. threading.Semaphore(DispatchSemaphore)→ 独立计数器对象,跨队列全局限流,只保护某一段代码

iOS这边也完完全全有一模一样的差异,两套工具,各自定位不同:

iOS 两套工具

OperationQueue.maxConcurrentOperationCount

等价 PythonThreadPoolExecutor(max_workers)

letqueue=OperationQueue()queue.maxConcurrentOperationCount=3//最多同时3个Operation执行foriin0..<10{queue.addOperation{//任务逻辑}}
  • 管控范围:只管控丢进这个OperationQueue里面的任务
    别的队列(全局GCD队列、另一个OperationQueue)完全管不到。
  • 原理:队列内部管理底层内核线程,最多同时跑N个任务;多余任务在队列内部排队。
  • 特点:任务一加入Operation,只要开始执行,就占用一条底层线程,直到整个Operation结束。整个任务生命周期占用线程,不能只对其中一小段代码做闸门。

GCD本身没有直接设置最大并发的API!GCD全局并发队列不能限制并发数,GCD要限制并发只能两种方案:

  1. DispatchSemaphore
  2. 自定义OperationQueue封装GCD任务

DispatchSemaphore(GCD信号量)

等价 Pythonthreading.Semaphore

letsem=DispatchSemaphore(value:3)letglobalQ=DispatchQueue.global()foriin0..<10{globalQ.async{//这里代码不限流,可以疯狂并发heavyCalc()sem.wait()//仅仅这一段做闸门networkRequest()sem.signal()}}
  • 它是独立计数器对象,不管任务来自哪个队列:global队列、自定义队列、别的OperationQueue,只要调用wait()就会被限流
  • 可以做到:只有中间一小段临界代码被限流,前后代码不受限制
  • 代价:wait()会阻塞当前内核线程,会引发线程爆炸。

核心差异(iOS版,和Python一一对应)

iOS工具管控什么管控范围特点Python对等物
OperationQueue.maxConcurrentOperationCount任务整体,控制同时执行多少Operation仅本队列内部的任务任务一旦执行,全程占住线程;不能只限制片段代码ThreadPoolExecutor(max_workers)
DispatchSemaphore一段临界区代码所有队列,全局生效可以只保护一小段代码;但是wait会阻塞内核线程,容易线程爆炸threading.Semaphore

iOS场景举例,什么时候选哪个

场景1:所有任务统一提交到同一个队列,整个任务都需要并发控制

比如:批量下载图片,每一个operation完整就是一次下载。
👉直接用OperationQueue + maxConcurrentOperationCount
简单干净,不要套信号量。

对应Python:全部任务丢进同一个ThreadPoolExecutor,设置max_workers。

场景2:多处不同来源的任务,都调用同一个接口,需要全局总并发限制

  • A处:global队列异步
  • B处:另一个OperationQueue
    两处都会调用同一个网络接口,希望全局最多同时3个网络请求。

OperationQueue管不到跨队列。
👉这时用全局DispatchSemaphore

对应Python:多处不同线程源,全局threading.Semaphore

场景3:一个任务,大部分逻辑不需要限流,只有中间一小块网络调用要限流

globalQ.async{doSomeHeavyLocalWork()//随便跑,不限流sem.wait()apiCall()//仅这里限流sem.signal()}

Operation做不到,Operation粒度是整个任务。只能用DispatchSemaphore。

Python:线程池任务内部,局部用threading.Semaphore保护一小段。

iOS里一个非常经典错误(和Python一样)

OperationQueue设置maxConcurrentOperationCount=5,外面再套一个DispatchSemaphore(value=2)

queue.maxConcurrentOperationCount=5//添加很多operation//operation内部执行 sem.wait()

会发生:底层一次性开5条内核线程,其中3条线程卡在sem.wait()原地阻塞休眠,线程被白白占用,浪费内核资源。

✅最佳实践:

  • 如果任务全部交给本队列:直接把maxConcurrentOperationCount设置成目标并发数,不要再叠加信号量。
  • 只有跨队列、局部代码段限流,才上DispatchSemaphore。

上面全部是GCD / OperationQueue(基于内核线程)

Swift Concurrency(async/await)世界的对应

  1. AsyncSemaphore👉 对应Pythonasyncio.Semaphore
    • Task是用户态对象,await sem.wait()挂起Task,归还底层worker线程,不会阻塞内核线程,没有线程爆炸问题
    • 同样是保护一段临界区,可以跨多处Task做全局限流。
    • Swift Concurrency没有类似ThreadPoolExecutor这种手动设置最大worker线程的API;worker线程数量由runtime自动等于CPU核心数,你不能手动调。

    Swift Concurrency中,你想控制并发,几乎就只用AsyncSemaphore

⚠️ Swift Concurrency千万不要混用DispatchSemaphore,会把协作池worker线程阻塞死。

把整套逻辑做一个总对照表

模型PythoniOS关键点
内核线程模型
(阻塞OS线程)
ThreadPoolExecutor(max_workers)OperationQueue.maxConcurrentOperationCount只管自己池/队列;任务全程占用线程
内核线程模型
(阻塞OS线程)
threading.SemaphoreDispatchSemaphore独立计数器;跨队列;可只保护片段;会阻塞线程,线程爆炸风险
协程模型
(挂起,释放OS线程)
asyncio.SemaphoreAsyncSemaphore挂起Task/协程,不阻塞内核线程;做并发闸门

一句话总结

  1. Python线程池 ≈ iOS OperationQueue:管自己内部全部任务,粒度是整个任务。
  2. Python threading.Semaphore ≈ iOS DispatchSemaphore:独立计数器,可以跨来源、只保护一小段代码,但代价是阻塞内核线程。
  3. 协程那一套(asyncio / Swift Concurrency)没有“线程池手动设置max workers”,靠协程信号量做闸门,不会阻塞内核线程。

补充一个很多iOS开发者踩坑:GCD全局并发队列不能设置最大并发数,GCD全局队列会疯狂开线程,所以GCD做并发限流只能依靠DispatchSemaphore,这也是为什么老项目大量见到DispatchSemaphore。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/24 2:59:22

前端面试必考:12个JavaScript核心知识点解析

1. 项目概述作为一名经历过上百场技术面试的前端工程师&#xff0c;我深知JavaScript基础在面试中的重要性。最近整理了一份"前端面试高频考点清单"&#xff0c;发现90%的面试都会围绕12个JS核心知识点展开。这些知识点看似基础&#xff0c;但能真正透彻理解的开发者…

作者头像 李华
网站建设 2026/8/24 2:58:58

FPGA DDR3控制器设计:从MIG IP核配置到AXI4接口实战

1. 项目概述&#xff1a;从SDRAM到DDR3的演进与MIG IP核的价值 如果你正在用FPGA做图像处理、高速数据采集或者需要大容量缓存的设计&#xff0c;大概率绕不开DDR3这颗“心脏”。但第一次接触DDR3控制器设计时&#xff0c;面对PHY、时序、MIG IP核这些概念&#xff0c;很容易一…

作者头像 李华
网站建设 2026/8/24 2:58:45

AI空间转场实战:手机拍摄+剪映智能补帧,Vlog电影感一键生成

最近在尝试制作一些生活Vlog时&#xff0c;发现一个痛点&#xff1a;拍摄的素材片段之间切换生硬&#xff0c;想要实现那些专业博主视频里流畅、富有创意的空间转场效果&#xff0c;需要学习复杂的剪辑软件&#xff08;如Premiere、After Effects&#xff09;&#xff0c;掌握关…

作者头像 李华
网站建设 2026/8/24 2:57:23

基于SSM框架的Java花店销售系统:毕业设计与实战指南

这次我们来看一个基于 SSM 框架的 Java 花店销售系统。对于计算机专业的同学来说&#xff0c;毕业设计是一个绕不开的坎&#xff0c;而一个功能完整、结构清晰、技术栈主流的项目往往是顺利过关的关键。这个“花店销售系统”就是一个典型的 Java Web 毕业设计选题&#xff0c;它…

作者头像 李华
网站建设 2026/8/24 2:57:21

RK3588 PCB设计实战:叠层规划与阻抗控制详解

1. 从一颗芯片到一块电路板&#xff1a;RK3588 PCB设计的核心挑战RK3588这颗芯片&#xff0c;相信很多做高性能嵌入式、边缘计算或者多媒体处理的朋友都不陌生。作为瑞芯微的旗舰级SoC&#xff0c;它集成了强大的CPU、GPU和NPU&#xff0c;接口丰富&#xff0c;性能强悍。但当我…

作者头像 李华
网站建设 2026/8/24 2:56:39

抽象工厂模式实战:Java代码示例与Spring应用解析

最近在项目重构中&#xff0c;我们遇到了一个典型问题&#xff1a;系统需要支持多种数据库&#xff08;如MySQL、Oracle&#xff09;和多种缓存服务&#xff08;如Redis、Memcached&#xff09;&#xff0c;并且未来可能增加新的数据库或缓存类型。如果为每一种组合&#xff08…

作者头像 李华