[课堂实践与项目]IOS多线程(1):NSThread的使用

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];

第一种方法是 类方法,第二种方法是实例方法,很明显,实例方法需要 start才能开始进程。


不适用NSThread,直接使用NSObject方法创建一个线程

[self performSelectorInBackground:@selector(selector) withObject:obj];

2)线程间通讯:线程完成下载之后通知主线程或者通知其他线程。

i:通知主线程

 [self performSelectorOnMainThread:@selector(updateProessView:) withObject:nil waitUntilDone:NO];

ii:通知其他线程,传递相应的Object对象

[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

2.实例讲解多线程之NSThread

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];
}

iii:实现view界面的更新,并不断自身回调

//完成界面的更新
- (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];

}

实例1其实是一个很愚蠢的线程使用。我们的线程操作并没有实现任何实际的方法,进度条的更新完全是依赖timer的改变进行刷新。


-----------------------------------------------------

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];
    
    
}

iii:实现 买票 的方法。由于是多线程,一定要注意线程锁的使用。

//线程锁
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];

}


你可能感兴趣的:(网络,课堂实践与项目,线程)