[iOS]深入浅出 iOS 之多线程 NSThread
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 operations是基于 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];
}
}
lock 阻塞等待
trylock 非阻塞
我们可以使用指令 @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) networkReachabilityDidUpdate:(NetworkReachability*)reachability
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(reachabilityChanged) object:nil];
[self performSelector:@selector(reachabilityChanged) withObject:nil afterDelay:0.1f];
}
cancelPreviousPerformRequestsWithTarget是终止上次performSelector的Delay调用
上面例子是防止在afterDelay时间内重复调用reachabilityChanged
如在我们在某个 线程 中下载数据,下载完成之后要通知主线程 中更新界面等等,可以使用如下接口:
- (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 事件。
转载于:https://www.cnblogs.com/iOSJason/p/4079845.html
[iOS]深入浅出 iOS 之多线程 NSThread相关推荐
- [Cocoa]深入浅出Cocoa之多线程NSThread
深入浅出Cocoa之多线程NSThread 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循"署名-非商业用途-保持一致"创作公用协议 iOS ...
- iOS 开发中的多线程
线程.进程 什么是线程.进程 有的人说进程就像是人的脑袋,线程就是脑袋上的头发~~.其实这么比方不算错,但是更简单的来说,用迅雷下载文件,迅雷这个程序就是一个进程,下载的文件就是一个线程,同时下载 ...
- iOS 与OS X多线程和内存管理 笔记 ARC与所有权修饰符
注:本文为笔记形式,所以很多都是摘抄的.<<iOS 与OS X多线程和内存管理>>书中写的很棒,简单易懂,建议各位看官自己去看看. ####ARC和MRC 前一篇主要是MRC环 ...
- iOS开发网络篇—多线程断点下载
iOS开发网络篇-多线程断点下载 说明:本文介绍多线程断点下载.项目中使用了苹果自带的类,实现了同时开启多条线程下载一个较大的文件.因为实现过程较为复杂,所以下面贴出完整的代码. 实现思路:下载开始, ...
- 移动开发在路上-- IOS移动开发系列 多线程二
最近太忙没太多的时间,忙碌的码农生活空下来一点时间,都会挤出来看一些技术或者咨询的文章,废话不多说,直奔主题. 接着上一次的继续说. 定时器在多线程的使用 NSRunLoop 是线程相关的基础框架的一 ...
- 《Objective-C高级编程 iOS与OS X多线程和内存管理》读书笔记
<Objective-C高级编程 iOS与OS X多线程和内存管理>读书笔记 第一章:自动引用计数 自己生成的对象,自己所持有. 非自己生成的对象,自己也能持有 不再需要自己持有的对象时释 ...
- iOS进阶 - iOS如何监控崩溃
转载自:https://blog.csdn.net/qxuewei/article/details/90760508 iOS进阶 - iOS如何监控崩溃 几种常见的崩溃 数组越界:给数组添加 nil: ...
- iOS:iOS开发非常全的三方库、插件、大牛博客等等
iOS开发非常全的三方库.插件.大牛博客等等 github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章 ...
- iOS开发--iOS及Mac开源项目和学习资料
文/零距离仰望星空(简书作者) 原文链接:http://www.jianshu.com/p/f6cdbc8192ba 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". ...
- ios::ate ios::app ios::out ios::in ios::trunc ios::binary(组合总结)
一.情况1 [file1会被截断] ofstream out("file1"); ofstream out("file1", ofstream::out); o ...
最新文章
- 使用Python创建MySQL数据库实现字段动态增加以及动态的插入数据
- SAP QM 使用QP01事务代码真的不能创建含有Multiple Specification的检验计划
- 阿里移动|《蚂蚁金服移动端高可用技术实践》
- BZOJ1192: [HNOI2006]鬼谷子的钱袋
- guava-collections
- 使用Custom.pll修改标准Form的LOV
- Git for Windows之推送本地版本库到远程仓库
- C++右值引用与转移语义
- 前端学习(2452):封装数据接口
- c++ 返回智能指针_C++核心指南(17) I.11 禁止使用指针(T*)或引用(T)来转移所有权...
- vue父子之间数据传递
- mybatis plus 批量更新数据_Mybatis 多字段组合唯一 并批量添加不重复数据
- 2018.09.29 bzoj3885: Cow Rectangles(悬线法+二分)
- java转码工具_java转码工具native2ascii
- 重磅 | 完备的人工智能AI 学习——基础知识学习路线,所有资料免关注免套路直接网盘下载
- 接口安全评估基本流程
- 华为中兴为何对未来信心十足?
- tensorflow 常遇函数
- 关于 ‘else‘ without a previous ‘if‘错误
- 区块链+支付:区块链技术是什么?它如何在支付行业中使用?