首页 > 代码库 > iOS多线程的初步研究(一)-- NSThread
iOS多线程的初步研究(一)-- NSThread
iOS多线程的初步研究(一)
===
来源: http://www.cnblogs.com/sunfrog/p/3243230.html
NSThread
对于多线程的开发,iOS系统提供了多种不同的接口,先谈谈iOS多线程最基础方面的使用。产生线程的方式姑且分两类,一类是显式调用,另一类是隐式调用。
一、显式调用
显示调用的类为NSThread。一般构造NSThread的线程对象可通过两种方式:
初始化线程主方法:1.
类方法
.2.实例方法
可以拿到线程对象,便于以后终止线程。[NSThread detachNewThreadSelector:@selector(run:) toTarget:target withObject:obj]
;NSThread *newThread = [[NSThread alloc] initWithTarget:target selector:@selector(run:) object:obj];
定义NSThread的子类MyThread,然后实现main方法(即方法1中的run)。然后创建新对象:
MyThread *newThread = [[MyThread alloc] init];
启动线程
:[newThread start];终止线程
:实际上没有真正提供终止线程的api,但有个方法可以方便地利用cancel方法; 它是改变线程运行的一个状态标志,我们可以这样来利用:
在main方法中这样实现线程循环:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | - ( void )main { // 得到当前运行线程 while (![[NSThread currentThread] isCancelled]) { // thread loop [NSThread sleepForTimeInterval: 1.0 ]; //等同于sleep(1); [newThread cancel] } // release resources of thread } |
这时如果调用
[newThread cancel]
; 就可以终止线程循环了。NSThread有个类方法
exit
是用于立即结束当前线程的运行
(有点鲁莽),因为无法保证当前线程对资源的释放,所以不推荐使用
二、隐式调用
通过NSObject的Category方法调用:
1.在主线程中运行方法,wait表示是否阻塞这个方法的调用,如果为YES则等待主线程中运行方法结束。一般可用于在子线程中调用UI方法。
(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait
;2.在指定线程中执行,但该线程必须具备
run loop
。(void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;
3.隐含产生新线程。
(void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg;
三、NSThread的其它一些常用的方法
创建的线程是非关联线程(detached thread),即父线程和子线程没有执行依赖关系,父线程结束并不意味子线程结束。
(NSThread *)currentThread
; //获得当前线程(void)sleepForTimeInterval:(NSTimeInterval)ti;
//线程休眠(NSThread *)mainThread
; //主线程,亦即UI线程了(BOOL)isMainThread; + (BOOL)isMainThread
; //当前线程是否主线程(BOOL)isExecuting
; //线程是否正在运行(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需要显示网络数据时,可以简单地利用线程的执行顺序,避免显式的线程同步:
- UI线程调用
[threadObj performSelectorInBackground:@selector(loadData) withObject:nil];
子线程中回调UI线程来更新UI
?123456789101112131415- (
void
)loadData
{
//从网络中获取数据响应
//更新数据
//回调主线程(即系UI线程)
//uiObj 可以是TableView或者其他UI类
[uiObj performSelectorOnMainThread:
@selector
(updateUI) withObject:nil waitUntilDone:YES];
}
·也可以使用NSThread实现同样的功能,loadData相当于NSThread的main方法。·
iOS多线程的初步研究(一)-- NSThread