线程创建与启动
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 事件。