1.NSThread 2.Cocoa NSOperation 3.GCD(Grand Central Dispatch)

先说一下进程和线程的区别

  • 进城:进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内.比如说微信,扣扣,微博都是一个进城,他们都有自己的内存空间
  • 线程:1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程),线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行,比如使用酷狗播放音乐、使用迅雷下载电影,都需要在线程中执行

一,.NSThread

  • 优点:NSThread 比其他两个轻量级
  • 缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
  1. 创建方式
    - (id) initWithTarget:<#(nonnull id)#> selector:<#(nonnull SEL)#> object:<#(nullable id)#> //实例方法     
    + (void) detachNewThreadSelector:<#(nonnull SEL)#> toTarget:<#(nonnull id)#> withObject:<#(nullable id)#>//类方法

           注意:NSThread 实例方法需要调用- (void)start方法启动线程

        2.线程锁

           为了防止多个线程访问同一个方法,我们需要为线程加上一把锁

        3.我们可以加上@synchronized来为线程加上同步,这样我们就不用手动为线程加锁了

    @synchronized(<#token#>) {
        <#statements#>
    }

二.Cocoa NSOperation

  • 优点:1.不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。Cocoa operation 相关的类是 NSOperation ,NSOperationQueue。NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。2.如果你也熟悉Java,NSOperation就和java.lang.Runnable接口很相似。和Java的Runnable一样,NSOperation也是设计用来扩展的,只需继承重写NSOperation的一个方法main。相当与java 中Runnalbe的Run方法。然后把NSOperation子类的对象放入NSOperationQueue队列中,该队列就会启动并开始处理它。
  • 缺点:

       

    NSInvocationOperation * operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(printLargeNumber) object:nil];
    NSInvocationOperation * operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test) object:nil];
    
    NSOperationQueue * queue = [[NSOperationQueue alloc] init];
    //设置最大的并发个数
    [queue setMaxConcurrentOperationCount:2];
    [queue addOperation:operation1];
    [queue addOperation:operation2];
       注意:  线程池中的线程数,也就是并发操作数。默认情况下是-1,-1表示没有限制,这样会同时运行队列中的全部的操作。

三.GCD(Grand Central Dispatch)

  • 介绍:Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始之后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。现在的iOS系统都升级到7了,所以不用担心该技术不能使用。
  • GCD的工作原理:1.让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。2.一个任务可以是一个函数(function)或者是一个block。 GCD的底层依然是用线程实现,不过这样可以让程序员不用关注实现的细节。3.GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行。

        dispatch queue分为下面三种

  1. Serial :又称为private dispatch queues,同时只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。
  2. Concurrent :又称为global dispatch queue,可以并发地执行多个任务,但是执行完成的顺序是随机的。
  3. Main dispatch queue :它是全局可用的serial queue,它是在应用程序主线程上执行任务的。

       dispatch queue如何使用:

         1.常用的方法dispatch_async : 为了避免界面在处理耗时的操作时卡死,比如读取网络数据,IO,数据库读写等,我们会在另外一个线程中处理这些操作,然后通知主线程更新界面。

     

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{   
    // 耗时的操作   
    dispatch_async(dispatch_get_main_queue(), ^{   
        // 更新界面   
    });   
});
优点:1.代码简洁,2.GCD会自动根据任务在多核处理器上分配资源,优化程序

系统给每一个应用程序提供了三个concurrent dispatch queues。这三个并发调度队列是全局的,它们只有优先级的不同。因为是全局的,我们不需要去创建。我们只需要通过使用函数dispath_get_global_queue去得到队列,如下:


dispatch_queue_t globalQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

这里也用到了系统默认就有一个串行队列main_queue:

dispatch_queue_t mainQ = dispatch_get_main_queue();
虽然dispatch queue是引用计数的对象,但是以上两个都是全局的队列,不用retain或release。

       2、dispatch_group_async的使用 :dispatch_group_async可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。这个方法很有用,比如你执行三个下载任务,当三个任务都下载完成后你才通知界面说完成的了。下面是一段例子代码:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);   
dispatch_group_t group = dispatch_group_create();   
dispatch_group_async(group, queue, ^{   
    [NSThread sleepForTimeInterval:1];   
    NSLog(@"group1");   
});   
dispatch_group_async(group, queue, ^{   
    [NSThread sleepForTimeInterval:2];   
    NSLog(@"group2");   
});   
dispatch_group_async(group, queue, ^{   
    [NSThread sleepForTimeInterval:3];   
    NSLog(@"group3");   
});   
dispatch_group_notify(group, dispatch_get_main_queue(), ^{   
    NSLog(@"updateUi");   
});   
dispatch_release(group);

dispatch_group_async是异步的方法,运行后可以看到打印结果:

2012-09-25 16:04:16.737 gcdTest[43328:11303] group1 
2012-09-25 16:04:17.738 gcdTest[43328:12a1b] group2 
2012-09-25 16:04:18.738 gcdTest[43328:13003] group3 
2012-09-25 16:04:18.739 gcdTest[43328:f803] updateUi

每个一秒打印一个,当第三个任务执行后,upadteUi被打印。

         3、dispatch_barrier_async的使用:dispatch_barrier_async是在前面的任务执行结束后它才执行,而且它后面的任务等它执行完成之后才会执行

例子代码如下:

dispatch_queue_t queue = dispatch_queue_create("gcdtest.rongfzh.yc", DISPATCH_QUEUE_CONCURRENT);   
dispatch_async(queue, ^{   
    [NSThread sleepForTimeInterval:2];   
    NSLog(@"dispatch_async1");   
});   
dispatch_async(queue, ^{   
    [NSThread sleepForTimeInterval:4];   
    NSLog(@"dispatch_async2");   
});   
dispatch_barrier_async(queue, ^{   
    NSLog(@"dispatch_barrier_async");   
    [NSThread sleepForTimeInterval:4];   

});   
dispatch_async(queue, ^{   
    [NSThread sleepForTimeInterval:1];   
    NSLog(@"dispatch_async3");   
});

打印结果:

2012-09-25 16:20:33.967 gcdTest[45547:11203] dispatch_async1 
2012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_async2 
2012-09-25 16:20:35.967 gcdTest[45547:11303] dispatch_barrier_async 
2012-09-25 16:20:40.970 gcdTest[45547:11303] dispatch_async3

请注意执行的时间,可以看到执行的顺序如上所述。

        4、dispatch_apply :执行某个代码片段N次。

dispatch_apply(5, globalQ, ^(size_t index) { 
    // 执行5次 
});


本文使用的例子代码参考:http://cache.baiducontent.com/c?m=9d78d513d9981cee4fece4697d62c0156a43f0662ba4d0027fa5843897732c43506793ac56560772a7d20c6616de384bea812102371453bc8cb8fc5daccd866f6fd6286e365ac45613a004b29b18789437902db1f249b7e7ae6584aea582820b4ece5807798bed&p=c4759a46d6c51cfb1281c7710f0089&newp=8f78ce15d9c041a944f3c7710f0589231610db2151ddd60961&user=baidu&fm=sc&query=iOS%BF%AA%B7%A2+%B6%E0%CF%DF%B3%CC+%B2%A9%BF%CD&qid=fa5b06890000b490&p1=3




四.不显式创建线程的方法

[id performSelectorInBackground:<#(nonnull SEL)#> withObject:<#(nullable id)#>] //创建了一个子线程
[self performSelectorOnMainThread:<#(nonnull SEL)#> withObject:<#(nullable id)#> waitUntilDone:<#(BOOL)#>] //  回到主线程


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值