美文网首页
##iOS开发之多线程开发之NSThread

##iOS开发之多线程开发之NSThread

作者: 纳萨立克 | 来源:发表于2016-03-08 10:27 被阅读61次

    在每个iOS应用程序中,都存在一个线程用来显示界面,更新UI,处理触摸时间的主线程(Main),当我们的需求中需要有一个特别消耗时间的操作的时候,如果我们把这样的操作放在主线程中完成的话,就会造成主线程堵塞,界面卡死,这样极大的影响了用户体验.一般这种需求我们可以通过多线程在实现,把这样的耗时的操作放到另外的一个线程中去执行,提高了用户体验和运行效率.

    在iOS中的多线程主要有pthread,NSThread,GCD, NSOperation.

    技术方案 语言 线程生命周期 使用频率
    pthred C 程序员管理 几乎不用
    NSThread OC 程序员管理 偶尔使用
    GCD C 自动管理 经常使用
    NSOperation OC 自动管理 经常使用

    一.Ptheard (基本不使用)

    • 一套通用的多线程API
    • 适用于Unix\Linux\Window等系统
    • 跨平台\可移植
    • 使用难度大
    #import "ViewController.h"
    #import <pthread.h>
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    
    void * run(void *param)
    {
        for (NSInteger i = 0; i<50000; i++) {
            NSLog(@"-----%zd--%@", i, [NSThread currentThread]);
        }
        return NULL;
    }
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        pthread_t thread;
        
        pthread_create(&thread, NULL, run, NULL);
        
    }
    
    

    二. NSThread (偶尔使用)

    • 使用更加面向对象
    • 简单易用,可以直接操作线程对象

    1. NSThread的初始化

    • 动态方法

      -(instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0);
      
        /*
         1. selector的方法只能有一个参数 即object.
         2. Target:selector消息的发送对象
         3. object:selector的方法的唯一参数,没有参数传nil
         */
         
        NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:@""];
        //设置线程名字
        thread.name = @"ricky";
        //启动线程
        [thread start];
      
    • 静态方法

        + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
      
      
      ///方法调用后就会立刻创建线程,并且启动.
          [NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
      
    • 隐式创建线程方法

          [self performSelectorInBackground:@selector(run) withObject:nil];
      
      
    • 获取当前线程

      NSThread *currentThread = [NSThread currentThread];
      
      
    • 获取主线程

      NSThread *mainThread = [NSThread mainThread];
       //判断当前线程是否是主线程
       BOOL isMain = [NSThread isMainThread];
      
      
    • 让线程延迟执行

      [NSThread sleepForTimeInterval:2];// 让线程睡眠2秒(阻塞2秒)
      [NSThread sleepUntilDate:[NSDate distantFuture]];
      [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
      

    2. 线程间通讯

    • 在指定线程中执行
    [self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:YES];
    
    • 在主线程中执行
    [self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES];  
    
    
    • 在当前线程中执行
    [self performSelector:@selector(run) withObject:nil];  
    

    3. 线程安全

    在多线程中,多个线程同时对同一个资源进行操作的时候,就会出现线程安全的问题,解决这问题的方法是:我们给这个资源加锁.即当一个线程开始操作改资源的时候,会给改资源加上一把锁,这样其他的线程是不可以对该资源进行读写等操作,当线程对该资源的操作完成是,就会把锁打开,让其他的线程对该资源进行操作.加锁对于资源是比较消耗性能的.

    #import "ViewController.h"
    
    @interface ViewController ()
    /** 售票员01 */
    @property (nonatomic, strong) NSThread *thread01;
    /** 售票员02 */
    @property (nonatomic, strong) NSThread *thread02;
    /** 售票员03 */
    @property (nonatomic, strong) NSThread *thread03;
    
    /** 票的总数 */
    @property (nonatomic, assign) NSInteger ticketCount;
    
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        
        self.ticketCount = 100;
        
        self.thread01 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
        self.thread01.name = @"售票员01";
        
        self.thread02 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
        self.thread02.name = @"售票员02";
        
        self.thread03 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
        self.thread03.name = @"售票员03";
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        [self.thread01 start];
        [self.thread02 start];
        [self.thread03 start];
    }
    
    - (void)saleTicket
    {
        while (1) {
            //加锁,对该资源的锁必须为同一把锁
            @synchronized(self) {
                // 先取出总数
                NSInteger count = self.ticketCount;
                if (count > 0) {
                    self.ticketCount = count - 1;
                    NSLog(@"%@卖了一张票,还剩下%zd张", [NSThread currentThread].name, self.ticketCount);
                } else {
                    NSLog(@"票已经卖完了");
                    break;
                }
            }
        }
    }
    
    

    相关文章

      网友评论

          本文标题:##iOS开发之多线程开发之NSThread

          本文链接:https://www.haomeiwen.com/subject/qmlzkttx.html