iOS多线程——你要知道的NSThread都在这里

你要知道的iOS多线程NSThread、GCD、NSOperation、RunLoop都在这里

转载请注明出处 http://blog.csdn.net/u014205968/article/details/78323156

本系列文章主要讲解iOS中多线程的使用,包括:NSThread、GCD、NSOperation以及RunLoop的使用方法详解,本系列文章不涉及基础的线程/进程、同步/异步、阻塞/非阻塞、串行/并行,这些基础概念,有不明白的读者还请自行查阅。本系列文章将分以下几篇文章进行讲解,读者可按需查阅。

组织架构说明

本系列文章是按照相关多线程类的抽象层次撰写的,也就是说NSThreadFoundation框架提供的最基础的多线程类,每一个NSThread类的对象即代表一个线程,接下来苹果为开发者封装了GCD(Grand Central Dispatch)GCD相比于NSThread来说,提供了便捷的操作方法,开发者不需要再关注于管理线程的生命周期,也不需要自行管理一个线程池用于线程的复用,但GCD是以C函数对外提供接口,因此Foundation框架在GCD的基础上进行了面向对象的封装,提供了面向对象的多线程类NSOperationNSOperationQueue,抽象层次更高。

由于OCC语言的超集,开发者也可以选择使用POSIX标准的线程pthreadpthreadNSThread都是对内核mach kernelmach thread的封装,所以在开发时一般不会使用pthread

RunLoop是与线程相关的一个基本组成,想要线程在执行完任务后不退出,在没有任务时睡眠以节省CPU资源都需要RunLoop的实现,因此,正确的理解线程就需要深入理解RunLoop相关知识。

NSThread的使用姿势全解

组织架构说明中讲到,NSThread是对内核mach kernel中的mach thread的封装,所以,每一个NSThread的对象其实就是一个线程,我们创建一个NSThread对象也就意味着我们创建了一个新的线程。初始化创建NSThread的方法有如下几种:

/*
使用target对象的selector作为线程的任务执行体,该selector方法最多可以接收一个参数,该参数即为argument
*/
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

/*
使用block作为线程的任务执行体
*/
- (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

/*
类方法,返回值为void
使用一个block作为线程的执行体,并直接启动线程
上面的实例方法返回NSThread对象需要手动调用start方法来启动线程执行任务
*/
+ (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

/*
类方法,返回值为void
使用target对象的selector作为线程的任务执行体,该selector方法最多接收一个参数,该参数即为argument
同样的,该方法创建完县城后会自动启动线程不需要手动触发
*/
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;

下面分别举几个栗子:

/*
说明: 本文的栗子都是在单视图的工程中执行,防止主线程退出后,其他线程被退出,不方便实验。
*/

//线程的任务执行体并接收一个参数arg
- (void)firstThread:(id)arg
{
    for (int i = 0; i < 10; i++)
    {
        NSLog(@"Task %@ %@", [NSThread currentThread], arg);
    }
    NSLog(@"Thread Task Complete");
}

- (void)viewWillAppear:(BOOL)animated
{    
    [super viewWillAppear: YES];

    /*
    创建一个线程,线程任务执行体为firstThread:方法
    该方法可以接收参数@"Hello, World"
    */
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(firstThread:) object:@"Hello, World"];
    //设置线程的名字,方便查看
    [thread setName:@"firstThread"];
    //启动线程
    [thread start];    
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear: YES];
    NSLog("ViewDidAppear");
}

上面的栗子没有什么实际意义,仅仅为了展示如何创建并启动线程,启动程序后就可以看到程序输出了10次

Task <NSThread: 0x1c446f780>{
  number = 4, name = firstThread} Hello, World

上面输出了线程的名称,还输出了我们传入的参数,通过很简单的代码就可以创建一个新的线程来执行任务,在开发中尽量将耗时的操作放在其他线程中执行,只将更新UI的操作放在主线程中执行。

一般情况下,通过上述方法创建的线程在执行完任务执行体后就会退出并销毁,可以在firstThread:方法的第二个NSLog方法和viewDidAppear:方法的输出上打断点,然后运行程序查看线程信息,在第一个断点时即firstThread:方法的断点中,程序中线程信息如下图:

线程执行体执行时应用线程信息

从上图可以看到,现在程序中有一个线程名为firstThread,该线程即为我们创建的NSThread对象,而com.apple.main-thread(serial)即为主线程的名称,其中serial是指明主线程是串行的,这个内容会在GCD中进行讲解,我们可以通过类方法[NSThread mainThread]来获取主线程。接下来继续执行到第二个断点,程序中线程信息如下图:

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值