多线程

1⃣️pthread 几乎不用          生命周期:程序员管理

C语言,适用于UnixLinuxWindows等系统,跨平台、可移植,使用不方便

2⃣️NSThread 偶尔使用        生命周期:程序员管理

OC语言,使用更加面向对象,简单易用,可直接操作线程对象,用的比较多

    // 方式1

    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil];

    // 线程属性

    thread.name = @"yang";

    // 线程优先级 0~1 默认是0.5 越大优先级越高  只是CPU调用的可能性高一点

    thread.threadPriority = 1;

    // 开启线程 调用start 线程进入就绪状态,只是标示此线程可以执行了,并不是立即执行,只有在CPU有空闲的时候才会执行

    [thread start];

    

    NSThread *thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(test) object:nil];

    thread2.name = @"chen";

    [thread2 start];

    

    // 方式2 相当于上边的两行代码 创建一个线程后自动调用start方法

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

    

    // 方式3

//    [self performSelectorInBackground:@selector(test:) withObject:@"123"];

// 线程的几种状态

// 新生状态 创建一个线程

// 就绪状态 调用start方法

// 运行状态 不用我们管

// 阻塞状态 调用sleep方法

// 死亡状态 调用exit方法

// 睡5秒 当前线程进入阻塞状态

// [NSThread sleepForTimeInterval:5];

// 结束当前线程(死亡状态)

   [NSThread exit];

3⃣️GCD 纯C语言,会充分利用CPU的多核,自动管理线程的生命周期(创建、任务调度、销毁)

队列、延迟操作(dispatch_after)、Once、调度组

两个函数:

dispatch_sync(queue,block);   同步   将任务添加到队列,不会开启线程

dispatch_async(queue,block);   异步   将任务添加到队列,然后GCD管理的线程池中有空闲线程就会从队列中取出任务执行,只是开启线程,不会创建线程

GCD会自动将队列中得任务按先进先出的方式取出并交给对应线程执行

任务:要执行的操作(方法)      block指定,即代码块

队列:存放任务的集合

串行队列:一个接一个的调度任务    

并行队列:可以同时调度多个任务    

主    队列:全局串行,由主线程串行调度任务,只有一个

全局队列:本质就是一个无名的并行队列,可以用异步执行的方式验证,发现输出无序,说明是并行队列

// 全局队列和并发队列的区别

// 并发队列有名称,可以跟踪错误;全局队列没有

// 在ARC中不需要考虑内存释放,在MRC中需要手动释放内存,并发队列是create创建出来的,在MRC中见到create就要release;全局队列不需要release(只有一个)

几种情况:

串行队列:不管怎么执行都是顺序执行的    串行队列一次只调度一个任务

如果开多个线程,不能保证串行队列顺序执行,所以只开一个线程

并行队列:

同步:不创建线程,在当前线程执行,顺序执行

异步:开启多个线程 执行无序   (队列仍然是顺序取出的,并行队列只是可以同时调度多个任务,开启多个线程  导致  无序执行,如果开一个线程还是顺序执行的)

主    队列:先执行主线程中的代码,再执行队列中的任务

同步:主线程上的代码和队列中的任务相互等待,形成死锁

如果主线程正在执行代码,就不调度任务,而同步执行是要调度任务在当前线程执行,相互等待就形成了死锁

异步:在主线程上顺序执行

解决死锁问题:放入异步执行

延迟操作:

    //异步执行 演示延迟执行

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{

        NSLog(@"延迟操作----%@",[NSThread currentThread]);

    });

Once:看单例

调度组:

// 有时候需要在多个异步任务都执行完成之后继续做某些事情 这个时候需要用到调度组

// 比如下载歌曲,等待多个歌曲都下载完成之后,转到主线程提示用户

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{

    // 调度组的原理

    dispatch_group_t group = dispatch_group_create();

    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

    

    //添加一个任务

    dispatch_group_enter(group);   // group计数+1

    dispatch_async(queue, ^{

        NSLog(@"mj.avi %@",[NSThread currentThread]);

        dispatch_group_leave(group);  // 任务执行完成后 group计数-1

    });

    

    //添加一个任务

    dispatch_group_enter(group);

    dispatch_async(queue, ^{

        [NSThread sleepForTimeInterval:2];

        NSLog(@"111.avi %@",[NSThread currentThread]);

        dispatch_group_leave(group);

    });

    

    //添加一个任务

    dispatch_group_enter(group);

    dispatch_async(queue, ^{

        NSLog(@"3333.avi %@",[NSThread currentThread]);

        dispatch_group_leave(group);

    });

    

    dispatch_group_notify(group, dispatch_get_main_queue(), ^{

        NSLog(@"over");

    });

    //阻塞当前执行

//    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    

    NSLog(@"abc");

}

4⃣️NSOperation 生命周期自动管理

// NSOperation 抽象类,没有提供实现,一般作为父类来用,来约束子类都具有共同的属性和方法

// 是OC语言中基于GCD的面向对象的封装,使用起来比GCD更加简单(面向对象)

// NSOperation子类

// NSInvocationOperation

// NSBlockOperation

// 自定义子类继承NSOperation,实现内部相应的方法

// NSInvocationOperation

// 两种方法

// 创建操作 调用start方法

// 创建操作 把操作添加到队列中去执行

- (void)test1{

//    // 1 调用start方法执行 不经常使用

//    dispatch_async(dispatch_get_global_queue(0, 0), ^{

//    NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(demo) object:nil];

//        [op start];

//    });

    

    // 2 创建操作 添加到队列中执行

    //创建队列

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    for (int i = 0; i < 10; i ++) {

        //创建操作

        NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo) object:nil];

        //把操作添加到队列中   相当于GCD并行队列 异步执行 (内部执行和GCD一样)

        // 开启多个线程 无序

        [queue addOperation:op];

    }

}

// NSBlockOperation

- (void)test2{

//    // 队列

//    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//    //创建一个操作

//    NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{

//        NSLog(@"我是一个操作 %@",[NSThread currentThread]);

//    }];

//    //把操作添加到队列

//    [queue addOperation:op];

//    //  回调函数  当前操作完成之后做得事情

//    [op setCompletionBlock:^{

//        NSLog(@"我是回调函数 %@",[NSThread currentThread]);

//    }];

    

//    // 队列

//    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//    

//    for (int i = 0; i < 20; i ++) {

//        NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{

//            NSLog(@"%d  %@",i,[NSThread currentThread]);

//        }];

//    [queue addOperation:op];

//    }

    

//    // 更方便的操作

//    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

//    for (int i = 0 ; i<20; i++) {

//        //内部会帮我们创建操作,并把操作添加到队列中

//        [queue addOperationWithBlock:^{

//            NSLog(@"%d  %@",i,[NSThread currentThread]);

//        }];

//    }

    

    

    // 使用全局队列(队列属性)

    for (int i = 0; i < 20; i ++) {

        [self.queue addOperationWithBlock:^{

            NSLog(@"%d  %@",i,[NSThread currentThread]);

        }];

    }

}

// 设置最大并发数

_queue.maxConcurrentOperationCount = 2;

// 暂停  正在执行的任务会执行完成   后续的任务暂停

self.queue.suspended = !self.queue.isSuspended;

// 取消所有操作  会设置当前队列中所有的操作的canceled属性为yes

[self.queue cancelAllOperations];

// 操作之间依赖关系

- (void)test2{

    //模拟软件升级    下载   解压  通知用户

    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"下载 %@",[NSThread currentThread]);

    }];

    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{

        [NSThread sleepForTimeInterval:2];

        NSLog(@"解压 %@",[NSThread currentThread]);

    }];

    NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"通知用户 %@",[NSThread currentThread]);

    }];

    

    //设置  操作  之间的依赖关系      依赖关系可以跨操作队列

    [op2 addDependency:op1];

    [op3 addDependency:op2];

    //    [op1 addDependency:op3];

    

    

    //把操作添加到队列中   并行队列  异步执行

    [self.queue addOperations:@[op2,op1] waitUntilFinished:NO];

    

    [[NSOperationQueue mainQueue] addOperation:op3];

    

    NSLog(@"over");

}

// GCD 和 NSOperation的对比

// GCD是iOS4.0 推出的,主要针对多核cpu做了优化,是C语言的技术

// GCD是将任务(block)添加到队列(串行/并行/全局/主队列),并且以同步/异步的方式执行任务的函数

// GCD提供了一些NSOperation不具备的功能

// 一次性执行

// 延迟执行

// 调度组

// NSOperation是iOS2.0推出的,iOS4之后重写了NSOperation

// NSOperation将操作(异步的任务)添加到队列(并发队列),就会执行指定操作的函数

// NSOperation里提供的方便的操作

// 最大并发数

// 队列的暂定/继续

// 取消所有的操作

// 指定操作之间的依赖关系(GCD可以用同步实现)

原文地址:https://www.cnblogs.com/sunshineandsand/p/4602178.html