4.3 NSThread->1.0 创建线程

作者: 蓝田_Loto | 来源:发表于2016-04-15 14:19 被阅读75次

    本文并非最终版本,如果想要关注更新或更正的内容请关注文集,联系方式详见文末,如有疏忽和遗漏,欢迎指正。


    本文相关目录:
    ==================== 所属文集:4.0 多线程 ====================
    4.1 多线程基础->1.0 进程 & 线程
    ······················ 2.0 多线程简介
    4.2 pthread
    4.3 NSThread->1.0 创建线程
    ····················· 2.0 线程属性
    ····················· 3.0 线程状态/线程生命周期
    ····················· 4.0 多线程安全隐患
    ····················· 5.0 线程间通讯和常用方法
    4.4 GCD->1.0 GCD简介和使用
    ·············· 2.0 线程间的通信
    ·············· 3.0 其他用法
    ·············· 4.0 GCD 的定时器事件
    4.5 NSOperation->1.0 NSOperation简介
    ························ 2.0 NSOperationQueue
    ························ 3.0 线程间通信
    ························ 4.0 自定义NSOperation
    4.6 RunLoop - 运行循环
    ===================== 所属文集:4.0 多线程 =====================


    创建线程的3种方式:

    第一种:通过 NSThread 的对象方法 (alloc / init - start)
    
    第二种:通过 NSThread 的类方法   (detachNewThreadSelector)
    
    第三种:通过 NSObject 的方法
    

    1.1 创建线程1 - 对象方法alloc/init

    一个NSThread对象就代表一条线程

    创建方式1 : 通过NSThread的对象方法 (先创建初始化线程alloc/init , 再 start 开启线程) ——调试方便
    NSThread *thread = [[NSThread alloc]initWithTarget:<#(nonnull id)#>
                                              selector:<#(nonnull SEL)#>
                                                object:<#(nullable id)#> ];
    

    代码:

    #import "ViewController.h"
    
    @interface ViewController ()
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
      [super viewDidLoad];
      // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
      [self threadDemo1];
    }
    
    #pragma mark - 对象方法alloc/init
    /*
     - 在 OC 中,任何一个方法的代码都是从上向下顺序执行的
     - 同一个方法内的代码,都是在相同线程执行的(block除外)
     */
    - (void)threadDemo1 {
      NSLog(@"before %@", [NSThread currentThread]);
    
      // 线程一启动,就会在线程thread中执行self的run方法
      NSThread *thread = [[NSThread alloc] initWithTarget:self
                                                 selector:@selector(longOperation:)
                                                   object:@"THREAD"];
    
      //开启线程,通过start方法,就会将我们创建出来的当前线程加入到`可调度线程池`,供CPU调度
      //[thread start];执行后,会在另外一个线程执行 longOperation: 方法
      [thread start];
    
      NSLog(@"after %@", [NSThread currentThread]);
    }
    
    - (void)longOperation:(id)obj {
      NSLog(@"%@ - %@", [NSThread currentThread], obj);
    }
    
    - (void)didReceiveMemoryWarning {
      [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
    }
    
    @end
    

    打印结果:

    创建线程1 - 对象方法[2543:387435] before <NSThread: 0x7ffd28c00ca0>{number = 1, name = main}
    创建线程1 - 对象方法[2543:387711] <NSThread: 0x7ffd28d77be0>{number = 2, name = (null)} - THREAD
    创建线程1 - 对象方法[2543:387435] after <NSThread: 0x7ffd28c00ca0>{number = 1, name = main}
    

    Target:

    NSThread 的实例化方法中的 target 指的是开启线程后,在线程中执行 哪一个对象 的 @selector 方法

    NSThread *thread = [[NSThread alloc] initWithTarget:self.person
                                               selector:@selector(longOperation:)
                                                 object:@"THREAD"];
    
    [thread start];
    
    通过指定不同的 target 会在后台线程执行该对象的 @selector 方法
    
    不要看见 target 就写 self
    

    1.2 创建线程2 - 类方法

    创建方式2 : 通过NSThread的类方法 (创建线程后直接自动启动线程)
    [NSThread detachNewThreadSelector:<#(nonnull SEL)#>
                             toTarget:<#(nonnull id)#>
                           withObject:<#(nullable id)#> ];
    

    代码:

    #import "ViewController.h"
    
    @interface ViewController ()
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
      [super viewDidLoad];
      // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
      [self threadDemo2];
    }
    
    #pragma mark - 类方法
    - (void)threadDemo2 {
      NSLog(@"before %@", [NSThread currentThread]);
    
      // detachNewThreadSelector 类方法不需要启动,会自动创建线程并执行@selector方法
      // 它会自动给我们做两件事 :  1.创建线程对象  2.添加到`可调度线程池`
      // 通过NSThread的类和NSObject的分类方法直接加入到可调度线程池里面去,等待CPU调度
      [NSThread detachNewThreadSelector:@selector(longOperation:)
                               toTarget:self
                             withObject:@"DETACH"];
    
      NSLog(@"after %@", [NSThread currentThread]);
    }
    
    - (void)longOperation:(id)obj {
      NSLog(@"%@ - %@", [NSThread currentThread], obj);
    }
    
    - (void)didReceiveMemoryWarning {
      [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
    }
    
    @end
    

    打印结果:

    创建线程2 - 类方法[2647:404930] before <NSThread: 0x7fddf8f01eb0>{number = 1, name = main}
    创建线程2 - 类方法[2647:404930] after <NSThread: 0x7fddf8f01eb0>{number = 1, name = main}
    创建线程2 - 类方法[2647:405061] <NSThread: 0x7fddf8e0e7a0>{number = 2, name = (null)} - DETACH
    

    1.3 创建线程3 - 分类方法(NSObject)

    创建方式3 : 通过NSObject的分类方法 (隐式创建并直接自动启动线程) ——推荐,开发常用
    // 此方法在后台线程中执行 (即是 : 在子线程中执行)
    [self performSelectorInBackground:<#(nonnull SEL) #>
                           withObject:<#(nullable id) #> per];
    

    代码:

    #import "ViewController.h"
    
    @interface ViewController ()
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
      [super viewDidLoad];
      // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
      [self threadDemo3];
    }
    
    #pragma mark - 分类方法
    - (void)threadDemo3 {
      NSLog(@"before %@", [NSThread currentThread]);
    
      // performSelectorInBackground 是NSObject的分类方法,会自动在后台线程执行@selector方法
      // 没有 thread 字眼,隐式创建并启动线程
      // 所有 NSObject 都可以使用此方法,在其他线程执行方法
      // 通过NSThread的类和NSObject的分类方法直接加入到可调度线程池里面去,等待CPU调度
      // PerformSelectorInBackground 可以让方便地在后台线程执行任意NSObject对象的方法
      [self performSelectorInBackground:@selector(longOperation:)
                             withObject:@"PERFORM"];
    
      NSLog(@"after %@", [NSThread currentThread]);
    }
    
    - (void)longOperation:(id)obj {
      NSLog(@"%@ - %@", [NSThread currentThread], obj);
    }
    
    - (void)didReceiveMemoryWarning {
      [super didReceiveMemoryWarning];
      // Dispose of any resources that can be recreated.
    }
    
    @end
    

    打印结果:

    创建线程3 - 分类方法[2711:412522] before <NSThread: 0x7ff078c02320>{number = 1, name = main}
    创建线程3 - 分类方法[2711:412522] after <NSThread: 0x7ff078c02320>{number = 1, name = main}
    创建线程3 - 分类方法[2711:412751] <NSThread: 0x7ff078c0e390>{number = 2, name = (null)} - PERFORM
    

    方式2和方式3的优缺点 :

    优点:简单快捷
    缺点:无法对线程进行更详细的设置
    

    本文源码 Demo 详见 Github
    https://github.com/shorfng/iOS_4.0_multithreading.git




    作者:蓝田(Loto)
    出处: 简书

    如果你觉得本篇文章对你有所帮助,请点击文章末尾下方“喜欢”
    如有疑问,请通过以下方式交流:
    评论区回复微信(加好友请注明“简书+称呼”)发送邮件shorfng@126.com



    本文版权归作者和本网站共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。。

    相关文章

      网友评论

        本文标题:4.3 NSThread->1.0 创建线程

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