一、创建NSThread:
(1)使用NSThread类方法:detachNewThreadSelector:toTarget:withObject:
该方法3个参数分别指定了线程执行的方法,目标,和传递的对象。但是要注意,使用这个方法时,并没有返回任何对象供操作,所以无法管理生成的线程。该方法让系统分发出一个线程,管理权归系统所有。
(2)使用NSObject的实例方法:performSelectorInBackground:withObject:该方法效果和第一个方法基本上一样,目标为对象本身。
(3)使用NSThread的实例方法:initWithTarget:selector:object:该方法3个参数分别指定了线程执行的方法,目标,和传递的对象。初始化之后,手动调用start方法启动线程。线程对象由自己管理。
(4)子类化NSThread的方法:写一个类继承自NST hread类,重写-(void)main;方法。手动调用Start方法启动线程。
二、线程的内存管理:
在工程的主函数中,有系统自动创建的NSAutoreleasePool对象,供在主线程中运行的对象使用。在创建其它的线程时,NSAutoreleasePool对象需要自己来创建、管理。不使用NSAutoreleasePool的后果是,系统中自动释放的对象无法被最终释放,像滚雪球一样越滚越大,最终导致系统崩溃。
三、线程相关属性方法:
(1)设置线程名称:setName。
(2)配置线程的堆栈大小:setStackSize,需要在启动线程前调用。
(3)配置线程字典:threadDictionary,我们可以在返回的字典中添加需要保存的键值对,在该线程执行期间都有效。
(4)设置线程的优先级:setThreadPriority,值从0到1。代表最低到最高。
(5)当前线程状态:
isExecuting
isFinished
isCancelled
isMainThread
(6)线程环境状态
isMultiThreaded
currentThread
(7)线程等待以及退出
sleepUntilDate:
sleepForTimeInterval:
exit
cancel
四、线程间的通讯:线程间的通讯使用performSelector系列方法:
(1)在应用程序主线程中做事情:
performSelectorOnMainThread:withObject:waitUntilDone:
performSelectorOnMainThread:withObject:waitUntilDone:modes:
(2)在指定线程中做事情:
performSelector:onThread:withObject:waitUntilDone:
performSelector:onThread:withObject:waitUntilDone:modes:
(3)在当前线程中做事情:
performSelector:withObject:afterDelay:
performSelector:withObject:afterDelay:inModes:
(4)取消发送给当前线程的某个消息
cancelPreviousPerformRequestsWithTarget:
cancelPreviousPerformRequestsWithTarget:selector:object:
五、互斥锁:NSLock类
(1)NSLock的对象可以解决多线程中互斥操作的问题,它有两个内部状态,锁定(locked)和打开(unlocked)。用于解决多个窗口同时买票的情景。
(2)一般使用方法,在互斥代码前后分别加上lock方法和unlock方法。可以为每段互斥代码分别创建一个NSLock对象。
(2)lock方法:申请锁,如果锁为打开状态,将锁置为锁定状态,然后执行互斥代码。如果锁为锁定状态,则线程阻塞,直到申请到锁。
(3)unlock方法:互斥操作完成时,释放锁,将锁置为打开状态。
(4)tryLock方法:该方法返回Bool值,如果成功申请到锁,则返回YES,如果没有申请到锁,则返回NO,但是线程不阻塞。具体操作由程序员根据返回状态自己处理。
(5)lockBeforeDate方法:该方法和tryLock方法类似,返回值也为Bool值。和tryLock不同的是,多了一个时间限制。如果在规定时间内申请到锁,则返回YES,如果没有申请到锁,返回NO。
(6)互斥锁不支持递归,因为第一次申请到锁,在锁释放之前,是不可能再次申请到锁的,线程会锁死。
比如如下代码:
-(void)test(int m){
if(m <= 0){
retun;
}else{
[theLock lock];
m--;
[self test:m];
[theLock unlock];
}
}
六、递归锁:NSRecursiveLock类
(1)递归锁的实例方法和NSLock一样。
(2)NSRecursiveLock支持递归,只要是在一个线程里,锁可以多次被申请,而不会造成死锁。它会记录lock和unlock的次数,然后进行匹配,当两个方法的调用次数相等时,也就是递归执行完毕时,锁就会被释放。
七、条件锁:NSConditionLock类
(1)NSConditionLock类有NSLock类的所有方法,可以用来做互斥操作。增加的其它方法为条件锁方法。
(2)条件锁用来解决生产者-消费者这样情景的问题。
(3)NSConditionLock初始化方法:initWithCondition:,通过一个条件变量初始化。
假设我们定义两个状态,有票:HAS_PRODUCT,没票:NO_PRODUCT。初始化时为无票。
(4)生产者申请锁:lock,不用有条件,因为生产者生产不需要依赖消费者。
(5)生产者生产完毕之后:使用unlockWithCondition:HAS_PRODUCT方法,释放锁,并且改变状态为有票。
(6)消费者申请锁:lockWhenCondition:HAS_PRODUCT,申请锁,并且在有票的情况下才能获取到锁,否则线程会阻塞。
(7)消费者消费完毕之后:unlockWithCondition:empty?NO_PRODUCT:HAS_PRODUCT。释放锁,如果当前产品消费完了,则将状态修改为没票,否则修改为有票。
八、@synchronized使用
(1)该指令可以完成互斥锁能完成的任务,能够将objective-c中的对象当做一种互斥体来使用。
(2)使用示例:
id object = [[NSObject alloc] init];
@synchronized(object){
//在内部添加互斥操作
}
(3)示例中的object对象相当于一个NSLock对象,它在@synchronized(object)开始的时候被请求,在结束的时候被释放。
九、信号量:NSCondition
(1)NSCodition是一种特殊类型的锁,我们可以用它来同步线程执行的顺序。它分为信号态和非信号态。当NSCondition为等待状态时,为非信号态,反之为信号态。一个处于等待状态的线程,需要等待其它线程给他发送信号,才能唤醒。
(2)等待线程的使用过程:
锁住NSCondition对象;
连续检查条件属性;
若不满足条件,线程进入等待状态(锁自动被打开);
直到满足条件,执行任务;
解除NSCondition锁定
(3)另外一个线程唤醒线程的过程:
锁住NSCondition对象;
改变条件属性的值;
唤醒等待线程(如果只有一个线程在等待,使用signal,当有多个线程在等待,使用broadcast);
解除NSCondition锁定。
(4)示例代码:
NSCondition *theCondition = [[NSCondition alloc] init];
BOOL readyToGo = NO;
----------------------------------------
//线程1代码
[theCondition lock];//请求锁
while (readyToGo == NO){
[theCondition wait];//线程等待,锁自动打开
}
//在此执行任何代码
[theCondition unlock];//释放锁
----------------------------------------
//线程2代码:
[theCondition lock];//请求锁
readyToGo = YES;//重置条件属性
[theCondition signal];//将NSCondition置为信号态,将唤醒线程1
[theCondition unlock];//释放锁
十、死锁:两个或者两个以上的进程或者线程在执行过程中,因争夺资源而造成一种互相等待的情况。比如:
进程P1、P2,资源R1、R2;P1占用R1,P2占用R2;但此时P1想占用R2,又不想释放R1,P2想占用R1,但是又不释放R2,造成互相等待,从而造成死锁。