博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS multiple threads(1)-----NSThread
阅读量:5916 次
发布时间:2019-06-19

本文共 4021 字,大约阅读时间需要 13 分钟。

hot3.png

   多线程编程在任何一门语言中都是重中之重,必须牢牢掌握住,就不废话啦。
   iOS所支持的多线程编程范式有下面几种:
     
1、 Thread;
 
    2、Cocoa operations;
      3、Grand Central Dispatch (GCD) (iOS4 才开始支持);
   而iOS 支持多个层次的多线程编程,层次越高的抽象程度越高,使用起来也越方便,也是苹果最推荐使用的方法。上述的三种范式,抽象层次是从低到高,下面简要说明这三种不同范式特点吧:
     1、Thread 是这三种范式里面相对轻量级的,但也是使用起来最负责的,你需要自己管理thread的生命周期,线程之间的同步。线程共享同一应用程序的部分内存空间,它们拥有对数据相同的访问权限。你得协调多个线程对同一数据的访问,一般做法是在访问之前加锁,这会导致一定的性能开销。在 iOS 中我们可以使用多种形式的 thread:
     a、Cocoa threads: 使用NSThread 或直接从 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程。如果你选择thread来实现多线程,那么 NSThread 就是官方推荐优先选用的方式。
     b、POSIX threads: 基于 C 语言的一个多线程库,
     2、Cocoa operations是基于 Obective-C实现的,类 NSOperation 以面向对象的方式封装了用户需要执行的操作,我们只要聚焦于我们需要做的事情,而不必太操心线程的管理,同步等事情,因为NSOperation已经为我们封装了这些事情。 NSOperation 是一个抽象基类,我们必须使用它的子类。iOS 提供了两种默认实现:NSInvocationOperation 和 NSBlockOperation。
     3、Grand Central Dispatch (GCD): iOS4 才开始支持,它提供了一些新的特性,以及运行库来支持多核并行编程,它的关注点更高:如何在多个 cpu 上提升效率。
   下面,我们来依次举例细说上述几种方式创建多线程的方式和特点。
   首先,我们来看看 NSThread 的使用,包括创建,启动,同步,通信等相关知识。这些与 win32/Java 下的 thread 使用非常相似

   线程创建与启动 

   NSThread的创建主要有两种直接方式:

   1、 [NSThread detachNewThreadSelector:@selector(myThreadMainMethod:) toTarget:self withObject:nil];
   2、 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];    }}
   我们可以使用指令 来简化 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 事件。
   

转载于:https://my.oschina.net/chengliqun/blog/113814

你可能感兴趣的文章
[c++]指针创建数组不会调用构造函数
查看>>
ES6 之reduce的高级技巧
查看>>
crossplatform---Nodejs in Visual Studio Code 06.新建Module
查看>>
权限设计的RBAC原则
查看>>
MAC开发配置--Node和Npm
查看>>
CQOI2015 选数
查看>>
什么是算法,什么是数据结构
查看>>
将python文件加入到python的环境变量中
查看>>
Linux sed 替换第一次出现的字符串
查看>>
欧拉定理与扩展欧拉定理学习笔记
查看>>
BZOJ3502PA2012Tanie linie&BZOJ2288[POJ Challenge]生日礼物——模拟费用流+链表+堆
查看>>
vb.net获取网页的简单示例
查看>>
::范围解析操作符
查看>>
yum 无法使用解决方法
查看>>
Angular features and services overview
查看>>
github commit, issue, pull request, project
查看>>
mysql主从同步(3)-percona-toolkit工具(数据一致性监测、延迟监控)使用梳理
查看>>
沟通的无力
查看>>
AOE网
查看>>
go学习记录
查看>>