[TwistedFate]iOS多线程编程GCD

多线程

  • 进程:正在活动(运行的)一个应用程序,就是一个进程
  • 每一个进程 都至少有一个线程 (主线程)
  • 线程:每一个线程都是独立的,可以执行任务
  • 除了主线程以外的 都叫子线程
  • 子线程可以有 很多个 但是线程是耗费资源的
  • (一般最多不超过五条 注:三条最佳)
  • 主线程操作什么样的任务?
    (UI界面 按钮的点击 屏幕滚动 一切用户看的见的 都要在主线程当中操作)
  • 子线程也操作UI界面 会造成什么问题?
    (听主线程 还是子线程)
  • 程序退出后会清空线程的任务

  • 主线程 下载20G电影 (耗时)
    屏幕就会假死 卡住 下完才恢复

  • 比较大的耗时操作 又或者 用户看不到的操作 可以放到子线程当中去做 比如下载 解压缩 读取大型数据等可以在子线程当中进行操作
  • 多线程的原理:
    CPU在工作时,同一时间只能执行一个任务,
    之所以可以造成多条线程一起执行任务的假象,是因为CPU在进行高速的线程切换(调度),来达到多个任务一起执行的效果
  • 多线程的优点:
    1.可以大大提高执行任务的效率
    2.可以让用户 有更好的用户体验
    缺点:
    如果大量的开辟线程 会造成程序的卡顿 耗费过量的资源
    物极必反

简介

iOS有三种多线程编程的技术,分别是:
(一)NSThread
(二)Cocoa NSOperation
(三)GCD(全称:Grand Central Dispatch)
这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。

三种方式的优缺点介绍:

1)NSThread:
优点:NSThread 比其他两个轻量级
缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销
Cocoa NSOperation
优点:不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上。

2) Cocoa operation 相关的类是 NSOperation ,NSOperationQueue。
NSOperation是个抽象类,使用它必须用它的子类,可以实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。
创建NSOperation子类的对象,把对象添加到NSOperationQueue队列里执行。

3) GCD
Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。在iOS4.0开始之后才能使用。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术。现在的iOS系统都升级到7了,所以不用担心该技术不能使用。

介绍完这三种多线程编程方式,本文将依次介绍这三种技术的使用。

NSThread的使用

初始化线程
//  1.初始化 开辟一个子线程
//    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(download:) object:@"123"];
//    [thread start];

 //  2.开辟一个子线程 不用开始自动执行
    [NSThread detachNewThreadSelector:@selector(download:) toTarget:self withObject:@"123"];

selector :线程执行的方法,这个selector只能有一个参数,而且不能有返回值。
target :selector消息发送的对象
argument:传输给target的唯一参数,也可以是nil

第二种方式会直接创建线程并且开始运行线程,第一种方式是先创建线程对象,然后再运行线程操作,在运行线程操作前可以设置线程的优先级等线程信息

线程 休眠(延迟执行的效果)
    [NSThread sleepForTimeInterval:5];
获得当前线程以及判断是否主线程
//  当前线程
    NSLog(@"--------%@",[NSThread currentThread]);
//  判断当前线程 是否是主线程
    NSLog(@"%d",[NSThread isMainThread]);
结束当前线程
 [NSThread exit];
// 相当于 在这儿 return  只要退出当前的线程 后边的方法 一切方法都不执行了

Cocoa NSOperation的使用

使用NSOperation的方式有两种
一种是用定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。
另一种是继承NSOperation

NSInvocationOperation的使用
 //  需要把NSInvocationOperation对象 放进一个队列里 才能完成开启子线程

    //  创建一个队列
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    //  给队列 设置 最大并发数
    queue.maxConcurrentOperationCount = 1;

    //  开启一个线程(相当于 一个任务)
    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download:) object:@"12"];

    //  把任务添加到 队列中
    //  只需要把任务添加进队列中 不需要咱们来操作
    //  会自动执行 不是添加一个任务就开启一个线程
    //  这个操作是系统给的  有的线程 会被系统重复利用(优化)
    [queue addOperation:operation];

GCD

  • 全称Grand Central Dispatch
  • GCD的工作原理是:让程序平行排队的特定任务,根据可用的处理资源,安排他们在任何可用的处理器核心上执行任务。
  • GCD中的FIFO队列称为dispatch queue,它可以保证先进来的任务先得到执行。
    dispatch queue分为下面三种:
Serial

又称为private dispatch queues,同时只执行一个任务。Serial queue通常用于同步访问特定的资源或数据。当你创建多个Serial queue时,虽然它们各自是同步执行的,但Serial queue与Serial queue之间是并发执行的。

Concurrent

又称为global dispatch queue,可以并发地执行多个任务,但是执行完成的顺序是随机的。

Main dispatch queue

它是全局可用的serial queue,它是在应用程序主线程上执行任务的。

常用的方法dispatch_async

GCD会自动根据任务在多核处理器上分配资源,优化程序。
系统给每一个应用程序提供了三个concurrent dispatch queues。这三个并发调度队列是全局的,它们只有优先级的不同。因为是全局的,我们不需要去创建。我们只需要通过使用函数dispath_get_global_queue去得到队列

//  获取全局队列
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{   
    // 耗时的操作   
    dispatch_async(dispatch_get_main_queue(), ^{   
        // 更新界面   
    });   
});


dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_async(queue, ^{

        //  做请求的 耗时操作(同步请求)
        //  在子线程中 同步请求 就相当于异步请求
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://image.dianping.com/Groups/GroupPic/2007-04-11/www123_1538656_88829_L.jpg"]];

        UIImage *image = [UIImage imageWithData:data];


        //  回到主线程刷新界面
        //  取出主线程
        // dispatch_get_main_queue();
        dispatch_async(dispatch_get_main_queue(), ^{

            //  回到主线程要执行的任务 刷新UI
            UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];

            imageView.image = image;
            [self.view addSubview:imageView];
            [imageView release];

        });
    });


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_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");   
});
dispatch_apply
dispatch_apply(5, globalQ, ^(size_t index) { 
    // 执行5次 
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值