IOS多线程之NSThread、NSOperation、GCD

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);
        }
    });

你可能感兴趣的:(多线程)