IOS多线程之NSThread、NSOperation、GCD

来源:互联网 发布:python的turtle库 编辑:程序博客网 时间:2024/05/16 15:36

IOS中支持多线程操作,使用NSThread和NSInvocationOperation可以完成多线程功能。多线程的功能主要是为了防止阻塞主线程的工作(主要是UI操作和显示),使一些耗时的的操作在另一个线程中完成,完成后可以通知主线程来进行UI上的更新。多线程功能在实际开发中用的很多,最典型的就是网络请求和处理操作,下面主要来讨论一下Cocoa中的NSThread和NOperation:

一、NSThread
创建NSThread主要有两种方式:
1.使用类方法创建

[NSThread detachNewThreadSelector:@selector(doInBackgroud) toTarget:self withObject:nil];

2.使用传统方式创建

NSThread *thread = [[NSThreadalloc] initWithTarget:self selector:@selector(doInBackgroud) object:nil];[thread start];

两种方式的区别:
1.第一种方式会立即调用并执行线程,第二种必须调用start方法后才会开始执行线程,在此之前可以对线程进行一些设置,比如线程优先级等。第二种方式与Java中线程的使用类似。
2.使用类方法(Convenient Method)创建的线程不需要进行内存清理,而使用initWithTarget方法创建的线程需要当retainCount为0时调用release方法释放内存

第二 NSOperation
1 怎么样使用NSOperation?
NSOperation 本身是一个抽象类,所以要用它的子类进行创建对象。它的子类有:
1) NSInvocationOperation
2) NSBlockOperation
2 子类的具体使用
NSInvocationOperation
代码片段:

    NSInvocationOperation *invocation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(loadImage:) object:@"haha"];    invocation.queuePriority = NSOperationQueuePriorityHigh;    NSOperationQueue *queue = [[NSOperationQueue alloc]init];    [queue addOperation:invocation];

NSBlockOperation

    NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{        NSLog(@"cdscdsvdsvvv");    }];    [queue addOperation:block];

NSOperationQueue

NSOperation的start方法默认是同步执行任务,这样的使用并不多见,只有将NSOperation与NSOperationQueue进行结合,才会发挥出这种多线程技术的最大功效.当NSOperation被添加到NSOperationQueue中后,就会全自动地执行异步操作.

NSOperationQueue的种类:

自带主队列[NSOperationQueue mainQueue]: 添加到主队列中的任务都会在主线程中执行自己创建队列(非主队列)NSOperationQueue *queue = [[NSOperationQueue alloc] init];: 这种队列同时包含串行、并发的功能,添加到非主队列的任务会自动放到子线程中执行

向NSOperationQueue中添加操作:

[queue addOperation:invocation];; [queue addOperation:block];

设置NSOperationQueue的最大并发数

NSOperationQueue可以通过以下方法设置最大并发数,setMaxConcurrentOperationCount:,值得注意的是:当并发数为1就变成了串行执行任务

NSOperationQueue的暂停恢复和取消

取消NSOperation有一个cancel方法可以取消单个操作NSOperationQueue的cancelAllOperations相当于队列中的每个operation调用了cancel方法,会取消队列里面全部的操作.但是,不能取消正在进行中的任务,队列调用了cancelAllOperations后会等当前正在进行的任务执行完闭后取消后面的操作

挂起和恢复

isSuspended : 判断是否挂起setSuspended: YES表示挂起,NO表示恢复和取消功能类似,我们同样不能挂起正在运行中的操作,队列会等当前操作结束后将后面的操作暂停(挂起)

添加依赖和监听

通过设置操作间的依赖,可以确定这些操作的执行顺序如:[op3 addDependency:op1];[op3 addDependency:op2];表示op3会在op1op2都执行完毕后才执行添加依赖的时候要注意防止添加循环依赖,此外我们还可以在不同队列的operation之间添加依赖

监听

op.completeBlock可以监听一个操作执行完毕的时刻,这个block里面可以添加一些我们需要执行的操作这个block里面的操作仍然是在子线程执行,但不一定和被监听的操作在同一个线程

GCD
1 什么是GCD?

GCD全称Grand Central Dispatch 

2 GCD 实质是什么?

GCD 实质是C语言级别的多线程处理方式,效率高,功能强大

3 具体代码

    //获取系统的串行队列    /*    dispatch_queue_t mainSerialQueue = dispatch_get_main_queue();    dispatch_async(mainSerialQueue, ^{        //NSLog(@"当前线程是%@ 是否是主线程%@",[NSThread currentThread],[[NSThread currentThread]isMainThread] ?  @"YES" : @"NO" );    });    //系统自带的并行队列    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);    dispatch_async(concurrentQueue, ^{        //NSLog(@"当前线程是%@ 是否是主线程%d",[NSThread currentThread],[[NSThread currentThread]isMainThread]);    });    //GCD 创建队列    //参数1:队列的名字    //参数2:什么类型的队列(串行or并行),NULL就是串行    dispatch_queue_t queue = dispatch_queue_create("queue", NULL);    //在队列中添加线程    dispatch_async(queue, ^{        //在子线程中获取数据        NSURL *url = [[NSURL alloc]initWithString:URL_IMAGRZHILIN];        NSData *data = [NSData dataWithContentsOfURL:url];        UIImage *image = [UIImage imageWithData:data];        //在主线程里刷新UI        __block ViewController *vc = self;        dispatch_async(dispatch_get_main_queue(), ^{            vc.imageView.image = image;        });    });    */    //GCD创建串行队列    /*    dispatch_queue_t serialQueue = dispatch_queue_create("SerialQueue", DISPATCH_QUEUE_SERIAL);    dispatch_async(serialQueue, ^{        for (int i = 0; i < 20; i++) {            NSLog(@"%d****************",i);        }    });    dispatch_async(serialQueue, ^{        for (int i = 0; i < 20; i++) {            NSLog(@"++++++++++++++++%d",i);        }    });    */    //GCD创建并行队列    dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);    dispatch_async(concurrentQueue, ^{        for (int i = 0; i < 20; i++) {            NSLog(@"%d**************",i);        }    });    dispatch_async(concurrentQueue, ^{        for (int i = 0; i < 20; i ++) {            NSLog(@"+++++++++++++++++%d",i);        }    });
0 0