曾静的博客

但行好事,莫问前程.

嗨,我是曾静 (@devzeng),目前暂居深圳。


这是我用来记录平日学习笔记的地方,欢迎您的访问.

iOS多线程之NSThread

iOS创建线程的方式有三种,分别是NSThreadNSOperationGCD。这样三种编程方式从上到下,抽象度层次是由低到高,抽象度越高的使用越简单,也是Apple最推荐使用的。这里主要是介绍NSThread的相关使用要点,后续会继续介绍NSOperationGCD的使用方法。

创建线程

对于多线程的开发,iOS系统提供了多种不同的接口,先谈谈iOS多线程最基础方面的使用。产生线程的方式姑且分两类,一类是显式调用,另一类是隐式调用。

显式创建线程

(1)采用NSThread的detachNewThreadSelector:toTarget:withObject:的类方法来创建多线程

[NSThread detachNewThreadSelector:@selector(doSomethingInBackground:) toTarget:self withObject:nil];

参数意义:

  • (1)selector:线程执行的方法,该selector只能有一个参数,而且返回值是void
  • (2)target:selector消息发送的对象
  • (3)argument:传递给target的唯一参数,可以为nil

(2)采用NSThread的initWithTarget:selector:object:的实例方法来创建线程,可以获取线程对象方便日后终止线程

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomethingInBackground:) object:nil];

(3)继承NSThread类,实现main方法,然后创建MyThread的对象调用start的方法调用线程

- (void)main
{
    //do something in background
}

调用

MyThread *thread = [[MyThread alloc] init];
[thread start];

隐式创建线程

(1)在后台执行

- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg

(2)在指定的线程中执行

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait

(3)在主线程中执行,wait表示是否阻塞方法的调用,如果为YES表示等待主线程中运行方法结束,可用于在子线程中刷新UI

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait

NSThread的其他方法

创建的线程是非关联线程(detached thread),即父线程和子线程没有执行依赖关系,父线程结束并不意味子线程结束。

(1)获得当前线程

//获得当前线程
 + (NSThread *)currentThread; 

(2)让线程休眠指定的时间间隔

//线程休眠
+ (void)sleepForTimeInterval:(NSTimeInterval)ti; 

(3)获取主线程(UI线程)

//主线程,亦即UI线程
+ (NSThread *)mainThread; 

(4)当前线程是否是主线程

//当前线程是否主线程
- (BOOL)isMainThread;
+ (BOOL)isMainThread; 

(4)线程是否正在运行

//线程是否正在运行
- (BOOL)isExecuting; 

(5)线程是否结束

//线程是否已结束
- (BOOL)isFinished; 

非线程调用(NSObject的Category方法)

即在当前线程执行,注意它们会阻塞当前线程(包括UI线程):

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

以下调用在当前线程延迟执行,如果当前线程没有显式使用NSRunLoop或已退出就无法执行了,需要注意这点:

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

而且它们可以被终止:

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument;
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;

线程执行顺序

通常UI需要显示网络数据时,可以简单地利用线程的执行顺序,避免显式的线程同步:

(1)UI线程调用

[threadObj performSelectorInBackground:@selector(loadData) withObject:nil];

(2)子线程中回调UI线程来更新UI

- (void)loadData
{
    //query data from network
    //update data model
    //callback UI thread
    [uiObj performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:YES];
}

也可以使用NSThread实现同样的功能,loadData相当于NSThread的main方法。

参考资料

1、《iOS多线程编程之NSThread的使用》

2、《iOS多线程的初步研究(一)– NSThread》

最近的文章

微信公众平台开发之开启开发者模式

说起来接触微信公众平台账号开发差不多快有半年了,在这期间利用零散的时间也开发了个企业服务号。经过这个公众账号的开发,对目前微信公众平台的开放的API算是比较熟悉了,对于常见的消息类型(text、news、music、voice、location等)等都有了一些认识和在使用过程中的技巧有了一定的认识。在开发过程中遇到的一些问题也有了一些领悟,所以想将一些经验分享出来,让大家共同进步。开发者模式配置1、在浏览器中输入https://mp.weixin.qq.com或点此打开微信后台界面2、申请...…

WeChat继续阅读
更早的文章

iOS中的单例设计模式

在一个iOS应用的生命周期中,有时候我们只需要某个类的一个实例。例如,iOS设备都有一个重力加速计硬件设备,要访问设备在X轴、Y轴和Z轴上的重力加速度,就必然有一个类能够与硬件设备沟通来实时获取这些数据,这个类就是UIAccelerometer。除了实时地获取数据该类还能保持X轴、Y轴和Z轴的状态,但这个类只要一个实例就够了,如果有多个实例就会占用过多的内存。单例模式简单实现在objective-c中要实现一个单例类,至少需要做以下四个步骤:(推荐使用宏的方式来创建)(1)为单例对象实现一...…

iOS继续阅读