[iOS]深入浅出 iOS 之多线程 NSThread

2023-10-30

线程专题:http://www.cocoachina.com/bbs/read.php?tid=43852

 

OS 支持多个层次的多线程 编程,层次越高的抽象程度越高,使用起来也越方便,也是苹果最推荐使用的方法。 
 
 
下面简要说明这三种不同范式: 
 
Thread 是这三种范式里面相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程 之间的同步。线程 共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。 
你得协调多个线程 对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在 iOS 中我们可以使用多种形式的 thread: 
Cocoa threads: 使用NSThread 或直接从 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程。如果你选择thread来实现多线程 ,那么 NSThread 就是官方推荐优先选用的方式。 
POSIX threads: 基于 C 语言的一个多线程 库, 
 
Cocoa operati*****是基于 Obective-C实现的,类 NSOperation 以面向对象的方式封装了用户需要执行的操作,我们只要聚焦于我们需要做的事情,而不必太操心 线程 的管理,同步等事情, 
因为NSOperation已经为我们封装了这些事情。 NSOperation 是一个抽象基类,我们必须使用它的子类。iOS 提供了两种默认实现:NSInvocationOperation 和 NSBlockOperation。 
 
Grand Central Dispatch : iOS4 才开始支持,它提供了一些新的特性,以及运行库来支持多核并行编程,它的关注点更高:如何在多个 cpu 上提升效率。  
 
有了上面的总体框架,我们就能清楚地知道不同方式所处的层次以及可能的效率,便利性差异。下面我们先来看看 NSThread 的使用,包括创建,启动,同步,通信等相关知识。这些与 win32/Java 下的 thread 使用非常相似。  
 
线程 创建与启动  
NSThread的创建主要有两种直接方式: 
[NSThread detachNewThreadSelector:@selector(myThreadMainMethod:) toTarget:self withObject:nil]; 
和 
NSThread* myThread = [[NSThread alloc] initWithTarget:self 
                                        selector:@selector(myThreadMainMethod:) 
                                        object:nil]; 
[myThread start]; 
 
这两种方式的区别是:前一种一调用就会立即创建一个 线程 来做事情;而后一种虽然你 alloc 了也 init了,但是要直到我们手动调用 start 启动线程 时才会真正去创建线程 。 
这种延迟实现思想在很多跟资源相关的地方都有用到。后一种方式我们还可以在启动线程 之前,对线程 进行配置,比如设置 stack 大小,线程 优先级。 
 
还有一种间接的方式,更加方便,我们甚至不需要显式编写 NSThread 相关代码。那就是利用 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个 线程 : 
[myObj performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil]; 
其效果与 NSThread 的 detachNewThreadSelector:toTarget:withObject: 是一样的。 
 
 
线程 同步  
线程
 的同步方法跟其他系统下类似,我们可以用原子操作,可以用 mutex,lock等。 
iOS的原子操作函数是以 OSAtomic开头的,比如:OSAtomicAdd32, OSAtomicOr32等等。这些函数可以直接使用,因为它们是原子操作。 
 
iOS中的 mutex 对应的是 NSLock,它遵循 NSLooking协议,我们可以使用 lock, tryLock, lockBeforeData:来加锁,用 unLock来解锁。使用示例:  
BOOL moreToDo = YES; 
NSLock *theLock = [[NSLock alloc] init]; 
... 
while (moreToDo) { 
    /* Do another increment of calculation */ 
    /* until there’s no more to do. */ 
    if ([theLock tryLock]) { 
        /* Update display used by all threads. */ 
        [theLock unlock]; 
    } 

 
我们可以使用指令 @synchronized 来简化 NSLock的使用,这样我们就不必显示编写创建NSLock,加锁并解锁相关代码。  
- (void)myMethod:(id)anObj 

    @synchronized(anObj) 
    { 
        // Everything between the braces is protected by the @synchronized directive. 
    } 

  
还有其他的一些锁对象,比如:循环锁NSRecursiveLock,条件锁NSConditionLock,分布式锁NSDistributedLock等等,在这里就不一一介绍了,大家去看官方文档吧。 
 
 
用NSCodition同步执行的顺序  
NSCodition 是一种特殊类型的锁,我们可以用它来同步操作执行的顺序。它与 mutex 的区别在于更加精准,等待某个 NSCondtion 的线程 一直被 lock,直到其他线程 给那个 condition 发送了信号。 
下面我们来看使用示例: 某个线程 等待着事情去做,而有没有事情做是由其他线程 通知它的。 
 
 
[cocoaCondition lock]; 
while (timeToDoWork <= 0) 
    [cocoaCondition wait]; 
  
timeToDoWork--;  
// Do real work here. 
[cocoaCondition unlock]; 
 
其他 线程 发送信号通知上面的线程 可以做事情了: 
[cocoaCondition lock]; 
timeToDoWork++; 
[cocoaCondition signal]; 
[cocoaCondition unlock]; 
 
 
线程 间通信  
线程
 在运行过程中,可能需要与其它线程 进行通信。我们可以使用 NSObject 中的一些方法: 
在应用程序主线程 中做事情: 
performSelectorOnMainThread:withObject:waitUntilDone: 
performSelectorOnMainThread:withObject:waitUntilDone:modes: 
 
在指定 线程 中做事情: 
performSelector:onThread:withObject:waitUntilDone: 
performSelector:onThread:withObject:waitUntilDone:modes: 
 
在当前 线程 中做事情: 
performSelector:withObject:afterDelay: 
performSelector:withObject:afterDelay:inModes: 
 
取消发送给当前 线程 的某个消息 
cancelPreviousPerformRequestsWithTarget: 
cancelPreviousPerformRequestsWithTarget:selector:object: 
 
如在我们在某个 线程 中下载数据,下载完成之后要通知主线程 中更新界面等等,可以使用如下接口:- (void)myThreadMainMethod 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    // to do something in your thread job 
    ... 
    [self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO]; 
    [pool release]; 
}  
 
RunLoop  
说到 NSThread 就不能不说起与之关系相当紧密的 NSRunLoop。Run loop 相当于 win32 里面的消息循环机制,它可以让你根据事件/消息(鼠标消息,键盘消息,计时器消息等)来调度线程 是忙碌还是闲置。 
系统会自动为应用程序的主线程 生成一个与之对应的 run loop 来处理其消息循环。在触摸 UIView 时之所以能够激发 touchesBegan/touchesMoved 等等函数被调用, 
就是因为应用程序的主线程 在 UIApplicationMain 里面有这样一个 run loop 在分发 input 或 timer 事件。


http://mysuperbaby.iteye.com/blog/1555487


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[iOS]深入浅出 iOS 之多线程 NSThread 的相关文章

  • Ubuntu18.04安装OpenGL依赖库

    sudo apt get install build essential sudo apt get install libgl1 mesa dev sudo apt get install libglu1 mesa dev sudo apt
  • tabpanel页签的机制

    tabpanel页签的机制 页签展现渲染时 只会初始化渲染你所指定的activeTab这个子页签 其他的页签一律不渲染 所以也就不存在form的dom内容 如果没有指定activeTab页签不会初始化任何子页签 那么所有的form都不会得到
  • 【ARIMA-WOA-CNN-LSTM】合差分自回归移动平均方法-鲸鱼优化-卷积神经网络-长短期记忆神经网络研究(Python代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 1 1 ARIMA模型 1 2 鲸鱼优化算法 1 3 卷积神经网络 1 4 LSTM 模型 2 运行结果
  • uniapp Echart X轴Y轴文字被遮挡怎么办,或未能铺满整个容器

    有时候布局太小 使用echarts x轴y轴文字容易被遮挡 怎么解决这个问题呢 或者是未能铺满整个容器 方法1 直接设置 containLabel 字段 options grid containLabel true 方法2 间接设置 但是不
  • IDEA 【基础】 javaweb项目中 将maven的jar包,复制到web项目的 lib 文件夹

    自己在做小型javweb项目的时候经常遇到这种问题 java lang NoClassDefFoundError 明明maven已经添加依赖了 而且项目里面可以正常运行 但是启动tomcat运行的时候 却运行不了 博主琢磨半天 了解到 第三
  • 深度学习实战项目(三)-行人检测重识别yolov5+reid(跑通+界面设计)

    行人检测重识别yolov5 reid 跑通 界面设计 参考源代码 github 权重文件 根据github上面的网盘进行权重下载 检测 将 ReID resnet50 ibn a pth放在person search weights文件下
  • One-Stage Visual Grounding(单阶段语言指示的视觉定位)论文略读_2019-2020

    One Stage Visual Grounding 2019 2020年论文略读 1 Zero Shot Grounding of Objects from Natural Language Queries 2019 ICCV 改进工作
  • Linux 查看显卡型号

    输入以下命令 lspci grep i vga 可以查看显卡型号 但是是一串数字代码 可通过PCI devices网站进行查询 结果如下所示 GeForce RTX 3060 Lite Hash Rate 即为显卡信息
  • 浏览器刷新、关闭页面与统计在线人数

    项目中可能需要统计在线人数 也可能需要在用户在退出时进行用户注销登录 既为统计实时在线人数 也为及时清理暂时不再使用的session 节约资源提高性能 对于以上的情况 若用户使用页面的注销按钮退出登录 那一定万事大吉了 当实际中这种可能性很
  • Java面试题(1)-J2SE基础

    最近在为自己实习准备 看了网上各种面试经验贴 也和身边的小伙伴一起参加了不少牛逼IT企业的面试 这篇文章就将面试遇到的一些比较常见的问题整理一下 给大家一些参考 也为自己整理整理 J2SE基础 1 九种基本数据类型的大小 以及他们的封装类
  • 猿创征文

    猿创征文 国产数据库实战 使用docker部署PolarDB X云原生分布式开源数据库 一 PolarDB X介绍 1 PolarDB X简介 2 PolarDB X特点 二 检查docker版本 三 检查docker配置信息 四 下载Po
  • redis集群原理

    redis是单线程 但是一般的作为缓存使用的话 redis足够了 因为它的读写速度太快了 官方的一个简单测试 测试完成了50个并发执行100000个请求 设置和获取的值是一个256字节字符串 结果 读的速度是110000次 s 写的速度是8
  • MySQL高频面试题

    文章目录 1 什么是MySQL 2 关系型数据库和非关系型数据库 3 数据库三大范式是什么 4 一条 SQL 查询语句是如何执行的 5 引擎 MySQL存储引擎MyISAM与InnoDB区别 MyISAM索引与InnoDB索引的区别 Inn
  • 哈夫曼树带权路径长度

    一 长什么样 左边是普通树 右边是哈夫曼树 图a WPL 5 2 7 2 2 2 13 2 54 图b WPL 5 3 2 3 7 2 13 1 48 可见 图b的带权路径长度较小 我们可以证明图b就是哈夫曼树 也称为最优二叉树 二 怎么生
  • Vue实现swiper轮播组件

    目前市面上有很多轮播组件 但是有的不满足业务需求 因此也需要自己首先轮播组件 以下是一个用vue实现的轮播组件 带动画效果 可以自行设置轮播速度 选择是否需要分页器等 效果如下 思路 结构 一个轮播组件应该由三部分组成 一是轮播的元素 如图
  • 如何在内存中执行二进制代码之win平台

    大家可能会很好奇 我们的任意exe程序 不就是在内存中执行的二进制机器码吗 不 今天我要说的是 我们如何把实现指定功能的一段二进制机器码 放到我们的程序中 然后在需要的时候 直接调用它 当然 这段代码也有其他用途 故而有了shell cod
  • 公众号分享

    配置 gt 登录公众号 gt 设置与开发 gt 公众号设置 gt 功能设置 gt js安全域名域名 gt 网页授权域名 1 先拿集成微信 js 路径写自己的 import wxshare from common js wxShareModu

随机推荐

  • 【树莓派之旅】第01期:一根网线搞定树莓派可视化界面

    一次偶然的机会接触到了树莓派 于是就购了一个板子 入手快两个月了 由于一直忙于工作的事情 所以也就没折腾 今天拿出来的时候发现要想把树莓派运行起来还需要一些其他外接设备 一时也没去某宝或某东上采购 就利用手头现有的资源玩一下 于是就有了此文
  • Sentinel实现动态配置的集群流控的方法

    这篇文章主要介绍了Sentinel实现动态配置的集群流控 本文给大家介绍的非常详细 对大家的学习或工作具有一定的参考借鉴价值 需要的朋友可以参考下 介绍 为什么要使用集群流控呢 相对于单机流控而言 我们给每台机器设置单机限流阈值 在理想情况
  • 部署 - 前端部署https服务,并配置安全证书

    项目中要实现跨tab复制 剪切 粘贴 所以涉及到操作剪切板的操作 选用了navigator clipboard 但是该api有必须在https的服务下才能用 所以就需要把项目部署城https服务 vue cli中可以配置webpack达到启
  • Android OkHttp源码阅读详解一

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到教程 前言 源码阅读基于okhttp 3 10 0 Android中OkHttp源码阅读二 责任链模式 implementation com
  • 注解实现CRUD

    CRUD 我们可以在工具类创建的时候实现自动提交事务 这个是在MybatisUtils工具类里面的弄的 public static SqlSession getSqlSession return sqlSessionFactory open
  • react 加粗_React入门的家庭作业(1-2)

    作业前准备 React在他的官网上挂了一个入门教程 是做一个xxoo棋的小游戏 在教程的最后留下了6个作业题 现在就来完成一下 准备材料 作业是在已完成教程的基础上做的 所以这里预设已经做好了环境部署 写好了游戏代码 如果没有 可以把这个复
  • 深聊性能测试,从入门到放弃之:性能测试技术栈,看完这篇,保证刷新你对性能测试的认知~~

    性能测试技术栈 1 引言 2 性能测试基础 2 1 性能测试理论 2 2 测试开发技能 3 性能监听诊断 3 1 前端监听诊断 3 2 服务器监听诊断 3 2 1 Linux 3 2 2 Windows Server 3 3 中间件监听诊断
  • 实现http到https的重定向

    vim etc httpd conf httpd conf DocumentRoot var www html redirect temp https www a com RewriteEngine on RewriteRule https
  • tensorflow笔记【9】深度学习-几个经典网络的基本结构

    tensorflow笔记 9 深度学习 几个经典网络的基本结构 文章目录 前言 一 卷积神经网络 二 经典网络结构 1 自制CNN 2 LeNet 3 AlexNet 4 VGGNet 5 InceptionNet 6 ResNet 总结
  • Java - Java基础(一)

    一 计算机基础知识 1 计算机简介 第一台通用计算机 ENIAC 2 数据的存储和运算 计算机中对于数据的存储和运算 都是通过二进制数据来完成 3 人机交互方式 图形化界面 DOS命令行 D 切换盘符 dir 查看当前路径下的文件信息 cd
  • Android中的drawable像素密度适配详解

    本文大纲 1 为什么要分drawable xxx目录 2 Bitmap的介绍 3 不同drawable xxx中的图片内存测试 1 为什么要分drawable xxx目录 android项目资源中对于drawable文件夹可以分为以下类型的
  • 【Transformer】10、HRFormer:High-Resolution Transformer for Dense Prediction

    文章目录 一 背景 二 方法 三 效果 论文链接 https arxiv org abs 2110 09408 代码链接 https github com HRNet HRFormer 一 背景 ViT 的提出让人们看到了 Transfor
  • 一文弄懂神经网络中的BP反向传播算法

    注 本文转自 一文弄懂神经网络中的BP反向传播算法 Charlotte77 博客园 安利 Charlotte77 的深度学习系列博客 最近在看深度学习的东西 一开始看的吴恩达的UFLDL教程 英文版 有中文版就直接看了 后来发现有些地方总是
  • 网卡中断优化

    1 中断的配置 root zxinos etc init d irq balancer status Checking for service irqbalance running etc init d irq balancer 是linu
  • 浅谈sleep、wait、yield、join区别

    sleep sleep 方法是属于 Thread 类中的 sleep 过程中线程不会释放锁 只会阻塞线程 让出cpu给其他线程 但是他的监控状态依然保持着 当指定的时间到了又会自动恢复运行状态 可中断 sleep 给其他线程运行机会时不考虑
  • 小甲鱼学python学习笔记

    一 序章 1 python缩进问题 if a 0 else while a 0 2 字符串拼接与控制台输入输出 input 可从控制台读入数据 括号内地字符串为输入时的提示 输入结果可通过变量保存 print 控制台输出 s input p
  • Linux 常用指令大全

    我是目录 1 指令格式 2 Windows 和 Linux 通用内容 3 路径的命令 1 cd 切换到某个目录 相对路径 绝对路径 2 pwd 显示当前路径 3 ls 列出目录下的所有子目录与文件 或 文件的信息 4 目录 文件的指令 1
  • 技术干货:解密最受欢迎的开源 Serverless 框架弹性技术实现

    Knative 是一款基于 Kubernetes 的开源 Serverless 应用编排框架 其目标是制定云原生 跨平台的 Serverless 应用编排标准 Knative 主要功能包括基于请求的自动弹性 缩容到 0 多版本管理 基于流量
  • 前端面试实习生(基础题)

    前言 经过一年的学习 我对vue框架有了清楚的认识 我就想着去找实习工作 这些天我投了100多份简历 接到了两个线上笔试 第一个面试题使用vue完成一个网页的模块 有要有分页与传输数据 这不重要 很容易写出来了 关键是第二个线上笔试题 很基
  • [iOS]深入浅出 iOS 之多线程 NSThread

    线程专题 http www cocoachina com bbs read php tid 43852 OS 支持多个层次的多线程 编程 层次越高的抽象程度越高 使用起来也越方便 也是苹果最推荐使用的方法 下面简要说明这三种不同范式 Thr