一、什么是NSThread?NSThread是一种基于线程的轻量级多线程编程方法(相对于GCD和NSOperation)。一个NSThread对象代表一个线程,需要手动管理线程的生命周期。线程同步等问题。2、NSThread方法介绍1)动态创建NSThread*newThread=[[NSThreadalloc]initWithTarget:selfselector:@selector(threadRun)object:nil];动态方法返回一个新的线程对象,需要调用start方法启动线程2)StaticCreate[NSThreaddetachNewThreadSelector:@selector(threadRun)toTarget:selfwithObject:nil];由于静态方法没有返回值,如果需要获取新创建的线程,需要在selector中调用获取当前线程的方法3)线程启动[newThreadstart];4)线程暂停[NSThreadsleepForTimeInterval:1.0]; (以暂停一秒为例)[NSThreadsleepUntilDate:[NSDatedateWithTimeIntervalSinceNow:1.0]];NSThreadpause会起到阻塞当前线程的效果5)线程取消[newThreadcancel];cancelthread不会立即停止并退出线程,只是做一个状态记录(线程是否需要退出)6)Threadstop[NSThreadexit];stop方法会立即终止除主线程之外的所有线程(无论它们是否正在执行任务)并退出,需要在您控制所有线程状态时调用此方法,否则可能会导致内存问题。7)获取当前线程[NSThreadcurrentThread];8)获取主线程[NSThreadmainThread];9)iOS8之前的线程优先级设置[NSThreadsetThreadPriority:1.0];这个方法的priority的值设置比较混乱,因为你不知道你应该设置什么值比较合适,所以在iOS8之后,threadPriority添加了注释:Tobedeprecated;下面usequalityOfService是指在iOS8之后,推荐使用qualityOfService属性,通过量化优先级枚举值来设置qualityOfService枚举,取值如下:NSQualityOfServiceUserInteractive:***优先级,用于用户交互事件NSQualityOfServiceUserInitiated:secondhighestpriority,用于用户需要立即执行的事件不重要的任务比如为线程设置第二高的优先级:[newThreadsetQualityOfService:NSQualityOfServiceUserInitiated];3.常用的线程间通信类型有三种: 1。指定当前线程执行操作[selfperformSelector:@selector(threadRun)];[selfperformSelector:@selector(threadRun)withObject:nil];[selfperformSelector:@selector(threadRun)withObject:nilafterDelay:2.0]; 2。(在其他线程中)指定主线程执行操作[selfperformSelectorOnMainThread:@selector(threadRun)withObject:nilwaitUntilDone:YES];注意:在主线程更新UI 3。(在主线程中)指定其他线程执行操作[selfperformSelector:@selector(threadRun)onThread:newThreadwithObject:nilwaitUntilDone:YES];//这里指定为线程[selfperformSelectorInBackground:@selector(threadRun)withObject:nil];//这里指定为后台线程四、线程同步线程和其他线程可能共享一些资源。当多个线程同时读写同一个共享资源时,可能会发生冲突线程同步是指在一定时间内,只允许一个线程访问某种资源。iOS通过两种方式实现线程锁定:NSLock和@synchronized。出售方面,在广州和北京开窗销售。下面是先监听线程退出通知的代码,从而知道线程什么时候退出演唱会门票数量_ticketCount=50;创建两个子线程(代表两个窗口同时售票)NSThread*window1=[[NSThreadalloc]initWithTarget:selfselector:@selector(saleTicket)object:nil];window1.name=@"北京售票窗口";[window1start];NSThread*window2=[[NSThreadalloc]initWithTarget:selfselector:@selector(saleTicket)object:nil];window2.name=@"广州售票窗口";[window2start];线程启动后,执行saleTicket,并执行完成后会退出。为了模拟连续售票的过程,我们需要给它加一个循环-(void)saleTicket{while(1){//如果还有票,继续售票if(_ticketCount>0){_ticketCount--;NSLog(@"%@",[NSStringstringWithFormat:@"Remainingtickets:%ldwindow:%@",_ticketCount,[NSThreadcurrentThread].name]);[NSThreadsleepForTimeInterval:0.2];}//如果售完,则关闭票务窗口else{break;}}}执行结果:2016-04-0619:25:36.637MutiThread[4705:1371666]剩余票数:9窗口:广州售票窗口2016-04-0619:25:36.637MutiThread[4705:1371665]剩余票数:8窗口:北京售票窗口2016-04-0619:25:36.839MutiThread[4705:1371666]剩余门票:7窗口:广州售票窗口2016-04-0619:25:36.839MutiThread[4705:1371665]剩余门票:7窗口:北京售票窗口2016-04-0619:25:37.045MutiThread[4705:1371666]剩余门票:5窗口:广州售票窗口2016-04-0619:25:37.045MutiThread[4705:1371665]剩余门票:6窗口:北京售票窗口2016-04-0619:25:37.250MutiThread[4705:1371665]剩余门票:4窗口:北京售票窗口2016-04-0619:25:37.250MutiThread[4705:1371666]剩余门票:4窗口:广州售票窗口2016-04-0619:25:37.456MutiThread[4705:1371666]剩余门票:2窗口:广州售票窗口2016-04-0619:25:37.456MutiThread[4705:1371665]剩余门票:3窗口:北京售票窗口2016-04-0619:25:37.661MutiThread[4705:1371665]剩余票数:1窗口:北京票务窗口2016-04-0619:25:37.661MutiThread[4705:1371666]剩余票数:1-04-0619:25:37.867MutiThread[4705:1371666]{number=3,name=广州售票窗口}WillExit2016-04-0619:25:38.070MutiThread[4705:1371665]0){_ticketCount--;NSLog(@"%@",[NSStringstringWithFormat:@"Remainingtickets:%ldwindow:%@",_ticketCount,[NSThreadcurrentThread].name]);[NSThreadsleepForTimeInterval:0.2];}//售完则关闭售票窗口else{break;}}}}运行结果:2016-04-0619:31:27.913MutiThread[4718:1406865]剩余票数:11窗口:北京售票窗口2016-04-0619:31:28.115MutiThread[4718:1406866]剩余票数:10窗口:广州票window2016-04-0619:31:28.317MutiThread[4718:1406865]余票:9窗口:北京售票窗口2016-04-0619:31:28.522MutiThread[4718:1406866]余票:8窗口:广州售票窗口2016-04-0619:31:28.728MutiThread[4718:1406865]剩余票数:7窗口:北京售票窗口2016-04-0619:31:28.929MutiThread[4718:1406866]剩余票数:6窗口:广州售票窗口2016-04-0619:31:29.134多线程[4718:1406865]剩余票数:5窗口:北京售票窗口2016-04-0619:31:29.339MutiThread[4718:1406866]剩余票数:4窗口:广州售票窗口2016-04-0619:31:29.545MutiThread[4718:1406865]余票:3窗口:北京售票窗口2016-04-0619:31:29.751MutiThread[4718:1406866]余票:2窗口:广州售票窗口2016-04-0619:31:29.952MutiThread[4718:1406865】剩余门票:1窗口:北京售票窗口2016-04-0619:31:30.158MutiThread[4718:1406866]剩余票数:0窗口:广州售票窗口2016-04-0619:31:30.363MutiThread[4718:1406866]{number=3,name=广州售票窗口}WillExit2016-04-0619:31:30.363MutiThread[4718:1406865]{number=2,name=北京售票窗口}WillExit可以看到出的票数没有命令 线程的持续运行和退出我们注意到线程启动后,执行saleTicket后立即退出。线程怎么才能一直运行(窗口一直开着,随时可以给它分配卖演唱会门票的任务),答案是给线程加上runLoop```先监听线程退出通知,从而知道线程什么时候退出[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(threadExitNotice)name:NSThreadWillExitNotificationobject:nil];```//设置演唱会票数_ticketCount=50;创建两个子线程(代表同时卖票的两个窗口)initWithTarget:selfselector:@selector(thread2)object:nil];[window2start];然后我们为线程创建一个runLoop-(void)thread1{[NSThreadcurrentThread].name=@"北京售票窗口";NSRunLoop*runLoop1=[NSRunLoopcurrentRunLoop];[runLoop1runUntilDate:[NSDatedate]];//一直运行}-(void)thread2{[NSThreadcurrentThread].name=@"广州售票窗口";NSRunLoop*runLoop2=[NSRunLoopcurrentRunLoop];[runLoop2runMode:NSDefaultRunLoopModebeforeDate:[NSDatedateWithTimeIntervalSinceNow:10.0]];//自定义运行时间}然后就可以给线程分配任务了,这里我们让两个线程执行同一个任务(出票)[selfperformSelector:@selector(saleTicket)onThread:window1withObject:nilwaitUntilDone:NO];[selfperformSelector:@selector(saleTicket)onThread:window2withObject:nilwaitUntilDone:NO];运行结果:2016-04-0619:43:22.585MutiThread[4762:147820]剩余门票:11窗口:北京售票窗口2016-04-0619:43:22.788MutiThread[4762:1478201]剩余门票:10窗口:广州售票窗口2016-04-0619:43:22.993MutiThread[4762:1478200]剩余门票:9号窗口:北京售票窗口2016-04-0619:43:23.198MutiThread[4762:1478201]剩余门票:8号窗口:广州售票窗口2016-04-0619:43:23.404MutiThread[4762:1478200]剩余票数:7窗口:北京售票窗口2016-04-0619:43:23.609MutiThread[4762:1478201]剩余票数:6窗口:广州售票窗口2016-04-0619:43:23.810MutiThread[4762:1478200]剩余票数:5窗口:北京售票窗口2016-04-0619:43:24.011MutiThread[4762:1478201]剩余票数:4窗口:广州售票窗口2016-04-0619:43:24.216MutiThread[4762:1478200]剩余票数:3窗口:北京售票窗口2016-04-0619:43:24.422MutiThread[4762:1478201]剩余票数:2窗口:广州售票窗口2016-04-0619:43:24.628MutiThread[4762:1478200]剩余票数:1窗口:北京售票窗口2016-04-0619:43:24.833MutiThread[4762:1478201]剩余票数:0窗口:广州售票窗口2016-04-0619:43:25.039MutiThread[4762:1478201]{number=3,name=广州售票窗口}WillExit可以看到,当门票售罄时,两个线程并没有退出,而是继续运行。当达到指定时间时,线程2退出。如果线程1需要退出,我们需要手动管理比如我们让线程完成任务(售票)后自行退出,我们可以这样操作-(void)saleTicket{while(1){@synchronized(self){//如果还有票,继续售卖if(_ticketCount>0){_ticketCount--;NSLog(@"%@",[NSStringstringWithFormat:@"剩余票数:%ld窗口:%@",_ticketCount,[NSThreadcurrentThread].name]);[NSThreadsleepForTimeInterval:0.2];}//如果售完,关闭售票窗口else{if([NSThreadcurrentThread].isCancelled){break;}else{NSLog(@"soldout");//将当前线程标记为已取消[[NSThreadcurrentThread]cancel];//停止当前的线程窗口2016-04-0620:08:38.489MutiThread[4927:1577194]剩余票数:9窗口:广州票窗口2016-04-062016-08:38.690MutiThread[4927:1577193]剩余票数:8窗口:北京票窗口2016-04-062016-08:38.892MutiThread[4927:1577194]剩余票数:7窗口:广州票务窗口2016-04-062016-04-062016:08:39.094MutiThread[4927:1577193]剩余票数:6窗口:北京票务窗口2016-04-062016-04-0620:08:39.294MutiThread[4927:1577194]剩余票数:5窗口:广州售票窗口2016-04-062016:08:39.499MutiThread[4927:1577193]剩余票数:4窗口:北京售票窗口2016-04-062016:08:39.700MutiThread[4927:1577194]票编号:3窗口:广州售票窗口2016-04-0620:08:39.905MutiThread[4927:1577193]剩余票数:2窗口:北京售票窗口2016-04-0620:08:40.106MutiThread[4927:1577194]剩余门票:1窗口:广州售票窗口2016-04-0620:08:40.312MutiThread[4927:1577193]剩余门票:0窗口:北京售票窗口2016-04-0620:08:40.516MutiThread[4927:1577194]售完out2016-04-0620:08:40.516MutiThread[4927:1577193]售完2016-04-0620:08:40.517MutiThread[4927:1577193]{number=2,name=北京售票窗口16-Exit2004-0620:08:40.517MutiThread[4927:1577194]{number=3,name=广州售票窗口}WillExit如果确认两个线程都处于isCancelled状态,可以调用[NSThreadexit]方法终止线程