IOS开发之多线程使用

IOS开发之多线程使用

今天开更新的的一篇,有关 ios开发多线程的使用,说到线程,还得提一下进程。

进程:我的理解是由操作系统分配,拥有独立的空间,在这个空间里包含者多个线程,在同一个进程里的线程可以共享内存中的资源。一个应用程序可以包含多个进程,最明显的例子就是chrome浏览器,你每打开一个新页面,它的进程就增加一个。说的有点远了。

多线程:ios中的每个APP应用程序都有一个主线程,程序启动的时候他被创建,(调用main()时启动),它的生命周期是和应用程序绑定的,如果应用程序退出,那么这个主线程也会挂掉。

为什么要使用多线程?
比如你在主线程里某些逻辑执行的时间过长,妨碍其他逻辑执行,那么我们需要开启一个线程让这个逻辑块在这个这个线程里运行,从而不影响其他逻辑块的执行。最简单的例子:我们从网络请求数据,然后将请求到的数据用来刷新UI界面,然而在网络请求的这段时间如果实在同一个主线程下进行,那么就会发生在数据没有加载完的时候,UI界面卡死的现象,并且这段时间你什么都做不了。所以这时候我们需要把网络请求部分放在一个新开辟的线程里。这样就不会影响主线程逻辑的继续执行。(关于网络请求这块不一定非要开辟线程,这涉及到同步和异步的概念,以后还会说)

ios使用线程有3种方式,NSThread, NSOperationQueue,GCD 他们依次由高层到底层

下面会对他们的用法分别介绍:

一、NSThread
它是ios最表层的一种开启线程的方式,所以操作很方便。类方法如下:
- (void)addThread
{
    [NSThread detachNewThreadSelector:@selector(thread1) toTarget:self withObject:nil];
}

- (void)thread1
{
    NSLog(@"这里开辟了一个线程1");
}
还有一种是对象方法,这种方法是在创建完一个线程后需要手动开启,方法如下:
- (void)addThread
{
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(thread1) object:nil];
    [thread start];
}

- (void)thread1
{
    NSLog(@"这里开辟了一个线程1");
}
还有一种更方便,方法如下:
- (void)addThread
{
      [self performSelectorInBackground:@selector(thread1) withObject:nil];
}

- (void)thread1
{
    NSLog(@"这里开辟了一个线程1");
}
这三中方法,你可以任选一种

光创建远远不能满足某些需求,所以NSThead还提供了判断是否是多线程,是否为主线程,获取当前线程,让线程睡眠,以及退出当前线程等常用的方法;
//    判断是否为多线程
+ (BOOL)isMultiThreaded;
//    获取当前线程
+ (NSThread *)currentThread;
//    判断是否为主线程
- (BOOL)isMainThread
+ (BOOL)isMainThread
//    是当前线程睡眠指定时间
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

我只列举一些常用的,你还可直接去NSThead这个类里找你可能需要的方法。这里需要提一下,用NSThread创建的每个线程都默认了一个RunLoop,主线程是默认开启的,而子线程的RunLoop默认没有启动,当你需要对你的线程进行监控的时候,这时候你需要手动启动这个RunLoop。

二、NSOperationQueue
NSOperationQueue我了解的是它类似一种集合的管理,它的用法相当独特,但也有缺陷,当你用NSOperation 创建一个operation并将它添加到了OperationQueue中后,你将无法在对它进行操作,否则会出现错误,最简单用法如下:
- (void)addThread
{
        NSOperationQueue *threadQueue = [[NSOperationQueue alloc] init];
    [threadQueue addOperationWithBlock:^{
        NSThread *t = [NSThread currentThread];
        if (![t isMainThread]) {
            
            NSLog(@"这里开辟了一个线程");
            //  在这里处理你想要处理的事情
        }
    }];
}

这种用法很独特,用一个Block(block 以后我会单独的开一篇来详细说明)你可以将它理解为一个独立的任务块
如果你不能接受上面那一种方法,下面这种或许你能接受一些:
- (void)addThread
{
      //  创建线程
    NSOperationQueue *threadQueue = [[NSOperationQueue alloc] init];
    NSInvocationOperation *oper = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(thread1) object:nil];
    [threadQueue addOperation:oper];
}

- (void)thread1
{
    NSLog(@"这里开辟了一个线程");
}

三、Grand Central Dispatch(GCD)

终于到这个强大的GCD了,为什么这么说,它可以提高代码的执行效率,同时他在多核的情况下,利用率也是相对比较明显的,毕竟是将子线程平行排队,将可用的资源合理的分配到任何可用的处理器核心上并执行。具体用法如下:
- (void)addThread
{    
    //  创建一个队列
    dispatch_queue_t queue = dispatch_queue_create("线程名", NULL);
    
    //  创建异步线程
    dispatch_async(queue, ^{
        
        NSLog(@"这里开辟了一个线程");
        
        //  这里是在这个子线程里,你想要做的事
        //  ...
        
        //  当你需要重新回到主线程去做一些事,则调用下面的方法
        dispatch_async(dispatch_get_main_queue(), ^{
            
            NSLog(@"这里回到主线程");
            
            //  回到主线程做你需要做的事
        });
    });
}

好了,今天就写到这里吧。
(PS:原创不易,转载请标明出处吧)。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值