IOS多线程大致可以分为三类API:NSThread,GCD,NSOperation。
下面就先扼要说下 NSThread的使用步骤。
1)创建NSthread线程的两种方式。
1、[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil]; 2、NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil]; [myThread start];
不适用NSThread,直接使用NSObject方法创建一个线程
[self performSelectorInBackground:@selector(selector) withObject:obj];
2)线程间通讯:线程完成下载之后通知主线程或者通知其他线程。
i:通知主线程
[self performSelectorOnMainThread:@selector(updateProessView:) withObject:nil waitUntilDone:NO];
[self performSelector:@selector(selector) onThread:thread1 withObject:nil waitUntilDone:NO];
-------------------------------------------------
下面我们就NSThread进行学习。
1.看看NSThread的方法
@interface NSThread : NSObject { @private id _private; uint8_t _bytes[44]; } + (NSThread *)currentThread; //得到当前的线程 + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;//初始化一个线程并start。 + (BOOL)isMultiThreaded; //判断是不是多线程 - (NSMutableDictionary *)threadDictionary;//返回线程字典 //线程休眠 退出 + (void)sleepUntilDate:(NSDate *)date; + (void)sleepForTimeInterval:(NSTimeInterval)ti; + (void)exit; //得到 设置线程的优先级 + (double)threadPriority; + (BOOL)setThreadPriority:(double)p; - (double)threadPriority NS_AVAILABLE(10_6, 4_0); - (void)setThreadPriority:(double)p NS_AVAILABLE(10_6, 4_0);
//回调 + (NSArray *)callStackReturnAddresses NS_AVAILABLE(10_5, 2_0); + (NSArray *)callStackSymbols NS_AVAILABLE(10_6, 4_0);
//设置线程的名字 - (void)setName:(NSString *)n NS_AVAILABLE(10_5, 2_0); - (NSString *)name NS_AVAILABLE(10_5, 2_0); - (NSUInteger)stackSize NS_AVAILABLE(10_5, 2_0); - (void)setStackSize:(NSUInteger)s NS_AVAILABLE(10_5, 2_0); - (BOOL)isMainThread NS_AVAILABLE(10_5, 2_0); + (BOOL)isMainThread NS_AVAILABLE(10_5, 2_0); // reports whether current thread is main + (NSThread *)mainThread NS_AVAILABLE(10_5, 2_0);
//线程的初始化 - (id)init NS_AVAILABLE(10_5, 2_0); // designated initializer - (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument NS_AVAILABLE(10_5, 2_0); //上面的方法 需要使用 start 才能开启线程
- (BOOL)isExecuting NS_AVAILABLE(10_5, 2_0); - (BOOL)isFinished NS_AVAILABLE(10_5, 2_0); - (BOOL)isCancelled NS_AVAILABLE(10_5, 2_0); - (void)cancel NS_AVAILABLE(10_5, 2_0); - (void)start NS_AVAILABLE(10_5, 2_0); - (void)main NS_AVAILABLE(10_5, 2_0); // thread body method @end FOUNDATION_EXPORT NSString * const NSWillBecomeMultiThreadedNotification; FOUNDATION_EXPORT NSString * const NSDidBecomeSingleThreadedNotification; FOUNDATION_EXPORT NSString * const NSThreadWillExitNotification; @interface NSObject (NSThreadPerformAdditions)
//回归主线程的方法 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; // equivalent to the first method with kCFRunLoopCommonModes
//跳转到其他线程的方法 - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5, 2_0); - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0); // equivalent to the first method with kCFRunLoopCommonModes
//设置线程后台运行的方法 - (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg NS_AVAILABLE(10_5, 2_0); @end
1)实例1:如何创建和使用NSThread
2)实例2:如何安全的使用多线程NSthread。
1)实例1
如何使用NSThread
其实多线程的使用方式很简单,创建/init一个多线程,并执行相应的SEL方法。最后在mainThread中进行view刷新即可。
扼要概述:
i:创建一个多线程:不用手动开启的创建
- (IBAction)buttonPressed:(id)sender { //防止多次点击,按钮隐藏 [self.buttonStart setHidden:YES]; //创建一个线程 [NSThread detachNewThreadSelector:@selector(startTheBackGroundJob:) toTarget:self withObject:nil]; }
ii:执行相应的startTheBackGroundJob方法,内部到主线程进行界面的刷新。
//子线程开启的方法 - (void)startTheBackGroundJob:(id)sender { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; [self performSelectorOnMainThread:@selector(updateProessView:) withObject:nil waitUntilDone:NO]; [pool drain]; }
//完成界面的更新 - (void)updateProessView:(id)sender { self.progressView.progress += 0.1; float value = self.progressView.progress; if (value < 1) { [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateProessView:) userInfo:nil repeats:YES]; } else { [self.buttonStart setHidden:NO]; } //更新进度条的信息 self.labelResult.text = [NSString stringWithFormat:@"%.2f",value]; }
-----------------------------------------------------
2)实例2
简单的售票机制
i创建线程的机制很简单,使用勒init方法,当然,这种方式是需要进行start,才能开启的
- (IBAction)buttonPressed:(id)sender { thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(buyTickets:) object:nil]; // thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(buyTickets:) object:nil]; thread3 = [[NSThread alloc]initWithTarget:self selector:@selector(buyTickets:) object:nil]; [thread1 setName:@"thread___1"]; [thread1 start]; [thread2 setName:@"thread___2"]; [thread2 start]; [thread3 setName:@"thread___3"]; [thread3 start]; }
//线程锁
NSCondition *_ticketCondition;
- (void)buyTickets:(id)sender { [self.buttonStart setHidden:YES]; while (TRUE) { //进行死循环,只要票卖空才会break [_ticketCondition lock]; //锁定,安全保护 if (numberOfTickets > 0) { [NSThread sleepForTimeInterval:0.1]; scaleOfTickets++; numberOfTickets--; NSString *thread = [[NSThread currentThread]name]; NSLog(@"当前票数%d,已售票数%d,总票数%d,当前线程:%@",numberOfTickets,scaleOfTickets,numberOfTickets +scaleOfTickets,thread); }else { [self.buttonStart setHidden:NO]; UIActionSheet *sheet = [[UIActionSheet alloc]initWithTitle:@"票已售完" delegate:nil cancelButtonTitle:@"知道啦" destructiveButtonTitle:@"ok" otherButtonTitles:nil, nil]; [sheet showInView:self.view]; [sheet release]; break; } [self performSelectorOnMainThread:@selector(updateView:) withObject:[[NSThread currentThread]name] waitUntilDone:YES]; //调用view的刷新。 [_ticketCondition unlock];//售票完成,解锁 }
- (void)updateView:(id)sender { self.currentTickets.text = [NSString stringWithFormat:@"%d",numberOfTickets]; self.saledTickets.text = [NSString stringWithFormat:@"%d",scaleOfTickets]; self.currentThread.text = [NSString stringWithFormat:@"%@",sender]; }