美文网首页GCD的用法
多线程 Nsthread GCD 和 Nsopration 的

多线程 Nsthread GCD 和 Nsopration 的

作者: 你美依旧 | 来源:发表于2017-08-17 15:35 被阅读59次

    一  pthread : 

    /*

    参数:

    1.线程代号的地址

    2.线程的属性

    3.调用函数的指针

    4.传递给函数的参数

    返回值:

    - 如果是 0, 表示正确

    - 如果是非0,表示错误码

    void *--(*)--(void *)

    返回值--(函数指针)--(参数)

    void *  相当于 OC中的id

    */

    -(void)pthreadDemo{

    pthread_t threadID;

    NSString * str = @"hello 老王";

    /*

    - 在 ARC 开发中, 如果遇到 OC和C 语言中相同数据类型进行转换,需要使用__bridge "桥接"

    - 在 MRC 开发中,不需要桥接

    在 OC 中,如果是ARC开发,编译器会在编译的时候,自动根据代码结构,添加 retain , release, autorelease

    ARC 只负责 OC部分的代码,不负责C的代码. 如果C的代码里面出现了 retain/create/copy 字样的函数,都需要release

    */

    int result = pthread_create(&threadID, NULL, &demo, (__bridge void *)(str));

    if (result == 0) {

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

    NSLog(@"OK!");

    }

    }else{

    NSLog(@"error %d",result);

    }

    }

    void * demo(void *param){

    NSString * sss = (__bridge NSString *)(param);

    NSLog(@"%@---%@",[NSThread currentThread],sss);

    return NULL;

    }

    一  NSThread

    oc语言需要程序员手动管理线程

    //创建线程 开辟一个子线程 常用创建方法

     1  NSThread * thread = [[NSThread alloc]initWithTarget:self selector:@selector(demo:) object:@"thread"];

    //启动线程

    [thread start];

    //创建以后立即开启

    2  [NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"Detach"];

    //常用的方法

    3   [self performSelectorInBackground:@selector(longOperation) withObject:nil];

    延时操作

    [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];

    [NSThread sleepForTimeInterval:2.0];

    杀死线程

    //一旦强行终止线程,后续的所有的代码都不会执行

    //注意:在终止线程之前,应该注意释放之前分配的对象!否则出现内存泄露!

     4  [NSThread exit];

    二 优先级属性

    /*优先级

    * 优先级只能保证 CPU 调度的可能性会高!

    * 多线程的目的: 将耗时的操作放在后台,不阻塞主线程和用户的交互!

    * 建议: 尽量不要修改 优先级!

    * "优先级翻转"

    * 在多线程开发中,不要相信你看到的结果!!一定要理性的(冷静)分析!!

    */

    t2.threadPriority = 0.1;

    三  资源共享

    @synchronized

    //参数:就是能够加锁的任意 NSOjbect 对象

    //局部变量: 每个线程单独拥有的,无法锁住!!

    //注意: 锁一定要是所有线程共享的对象!!

    @synchronized (<#token#>) {

    <#statements#>

    //互斥锁 - 保证锁内的代码,同一时间,只有一条线程能够执行!!

    //互斥锁它的范围,应该尽量小,锁范围越大,效率越低!

    }

    三 GCD 相关用法

    1. 什么是GCD

    全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”

    纯C语言,提供了非常多强大的函数

    2. GCD的优势

    GCD是苹果公司为多核的并行运算提出的解决方案

    GCD会自动利用更多的CPU内核(比如双核、四核 为以后苹果公司推出多核提供兼容)

    GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)

    程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

    3.GCD中有2个核心概念

    任务:执行什么操作

    队列:用来存放任务

    GCD的使用就2个步骤

    定制任务

    确定想做的事情

    将任务添加到队列中

    GCD会自动将队列中的任务取出,放到对应的线程中执行

    任务的取出遵循队列的FIFO原则:先进先出,后进后出

    4 GCD常用方法

    1. 延时操作

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

    });

    2 一次执行操作(设置单列的时候经常用到)

    //GCD提供了一个一次执行的机制,不仅能够保证只会被执行一次.而且是线程安全的!

    //GCD-Once 内部是会加锁!! 但是 比普通的互斥锁 效率高 100多倍 苹果推荐使用这个

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

    });

    3 调度组 

    //MARK: 调度组

    -(void)group1{

    //1.队列

    dispatch_queue_t q = dispatch_get_global_queue(0, 0);

    //2.调度组

    dispatch_group_t g = dispatch_group_create();

    //3.添加任务,让队列执行,任务执行情况最终通知组

    dispatch_group_async(g, q, ^{

    NSLog(@"download A %@",[NSThread currentThread]);

    });

    dispatch_group_async(g, q, ^{

    [NSThread sleepForTimeInterval:1.0];

    NSLog(@"download B %@",[NSThread currentThread]);

    });

    dispatch_group_async(g, q, ^{

    [NSThread sleepForTimeInterval:0.8];

    NSLog(@"download C %@",[NSThread currentThread]);

    });

    //4. 所有任务执行完毕后,获得通知

    //用一个调度组,可以监听全局队列调度的任务,执行完毕之后,在主队列执行最终处理!

    //dispatch_group_notify 本身是异步的

    dispatch_group_notify(g, dispatch_get_main_queue(), ^{

    //更新UI,通知用户

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

    });

    NSLog(@"come here");

    }

    //MARK: 主队列,同步任务

    //阻塞主线程!!

    -(void)gcdDemo2{

    //1.队列  -> 一启动就有主线程,主队列只需要获取

    dispatch_queue_t q = dispatch_get_main_queue();

    NSLog(@"这里!!");

    //2.同步任务

    dispatch_sync(q, ^{

    NSLog(@"能来吗?");

    });

    NSLog(@"come here -- %@",[NSThread currentThread]);

    }

    5 GCD总结

    /**

    GCD 核心概念:将任务添加到队列,指定任务执行的方法

    - 任务

    - 使用block 封装

    - block就是一个提前准备好的代码块,在需要的时候执行

    - 队列(负责调度任务)

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

    - 并发对象:可以同时调度多个任务

    - 执行任务的函数

    - 同步执行: 当前指令不完成,就不会执行下一条指令

    - 异步执行: 当前执行不完成,同样可以执行下一条指令

    小结:

    - 开不开线程,取决于同步\异步. 同步,不开!  异步,开!

    - 开多少条线程,取决于队列,串行开一条,并发(异步)开多条!

    hank:开启子线程只能是异步!!!  线程多开\并发且异步

    只要是异步就开启子线程!!!

    全局队列 & 并发队列

    1. 名称,并发队列有名称,适合大型项目跟踪错误报告!

    2. release,在 MRC 开发时,并发队列需要使用 dispatch_release(q);

    结论:目前绝大多数软件都会使用全局队列.

    全局队列 & 串行队列

    全局队列(并发): 并发,能够调度多个线程,执行效率高!!!

    - 费电!!

    串行队列: 一个接一个,只能开启一条线程,执行效率低!!

    - 省电,省钱,省流量

    选择的依据: 根据用户的上网方式!!

    - WIFI ,可以开多条线程, 6条

    - 3G\4G,尽量少开线程,2~3 条

    四  NSOperation

    特点:   不能直接使用

    目的:  定义子类中共有的属性和方法

    子类:- NSInvocationOperation    - NSBlockOperation

    1.   创建   //    NSInvocationOperation 操作

    NSInvocationOperation * op = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(downloadImage:) object:@"Hank"];

    //start 方法,会在当前线程执行调度方法

    //    [op start];

    //1.队列

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

    //2.将操作添加到队列 - 会自动异步执行调度方法

    [q addOperation:op];

    2.    //NSBlockOperation 所有的代码都写在一起.更加好维护

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

    NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{

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

    }];

    [q addOperation:op];

    二  线程间的通讯

    [self.opQueue addOperationWithBlock:^{

    NSLog(@"耗时操作!! %@",[NSThread currentThread]);

    //主线程 更新UI ,主队列

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{

    NSLog(@"UIUIUI --- %@",[NSThread currentThread]);

    }];

    }];

    三  依赖关系

    /**

    需求:从网上下载视频\完成之后解码\通知用户

    */

    //1.下载

    NSBlockOperation * op1 = [NSBlockOperation blockOperationWithBlock:^{

    [NSThread sleepForTimeInterval:3.0];

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

    }];

    //2.解码

    NSBlockOperation * op2 = [NSBlockOperation blockOperationWithBlock:^{

    [NSThread sleepForTimeInterval:2.0];

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

    }];

    //3.通知用户

    NSBlockOperation * op3 = [NSBlockOperation blockOperationWithBlock:^{

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

    }];

    //NSOperation 提供了依赖关系

    //NSOperation 的所有的操作都是异步执行的,但是为了建立任务之间的依赖,提供了dependency的功能

    //GCD中,通过同步任务来实现,也可以通过串行队列!

    [op2 addDependency:op1];//op2 依赖于 op1  == op1 执行完毕 op2 开始执行

    [op3 addDependency:op2];

    // !!千万注意!!!:  不要循环依赖!!!!,一旦指定了循环依赖,队列就不能执行被循环依赖的操作了!!

    //不会造成死锁!  但是 以前的版本 会死锁!!

    //    [op1 addDependency:op3];

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

    //主线程通知用户

    [[NSOperationQueue mainQueue] addOperation:op3];

    NSLog(@"come here");

    四  取消线程

    //提示: 取消操作,同样不会取消正在执行中的操作

    [self.opQueue cancelAllOperations];

    五 暂停/恢复线程

    //在设置队列的暂停属性时,并不会判断队列中是否有操作!

    //如果不希望用户产生困惑,可以提前做判断

    //判断队列中当前是否有操作

    if (self.opQueue.operationCount == 0){

    NSLog(@"没有操作!!!");

    return ;

    }

    if (self.opQueue.isSuspended) {

    //在暂停的时候,队列中的操作数,是包含正在执行的操作!!

    NSLog(@"继续 %tu",self.opQueue.operationCount);

    self.opQueue.suspended = NO;

    }else{

    //再次继续运行的时候,如果之前执行的操作已经完成,队列中的操作数就只有未调度的了!!

    NSLog(@"暂停 %tu",self.opQueue.operationCount);

    self.opQueue.suspended = YES;

    }

    六 最大线程

    //设置同时最大并发操作数量

    //WIFI: 5~6

    //2G/3G/4G: 2~3

    self.opQueue.maxConcurrentOperationCount = 2;

    //向队列添加任务

    //从 iOS 8.0 开始,无论使用GCD 还是 NSOperation, 都会开启很多线程

    //在 iOS 7.0 以前,GCD 通常只会开启 5 ~ 6 条线程!

    //目前线程数量多说明:

    //1.底层的线程池更大了,能够拿到的线程资源更多了!

    //2.对控制同时并发的线程数,要求就更高!

    GCD和NSOpration的比较

    /*

    NSOperation 是苹果公司大力推荐的"并发"技术! 开发者已经不需要关心线程以及线程的生命周期!

    ,而且我们逃离了GCD的 并发还是串行 异步还是同步!

    NSOperation 的核心概念: 将"操作" 添加到 "队列"

    GCD的核心概念: 将"任务"添加到队列,指定任务的执行函数(方法)

    ----------------------------------------------------------------------------------

    GCD & NSOperation 的对比

    GCD 在 iOS 4.0推出的,主要针对多核处理器做了优化的并发技术,是 C 语言!

    - 将"任务"[block]"添加到"队列[串行/并发/主队列/全局],并且指定执行任务的函数[同步/异步]

    - 线程间的通讯 dispatch_get_main_queue()

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

    - 一次执行(单例设计模式最常用)

    - 延迟执行

    - 调度组

    - 等等...

    NSOperation 在 iOS 2.0 推出的!

    - 将操作[异步执行的任务] 添加到 队列[并发队列],就会立刻异步执行

    - mainQueue

    - 提供了一些 GCD 实现起来比较困难的功能

    - 最大并发线程数

    - 队列的暂停/继续

    - 取消所有操作

    - 指定操作之间的依赖关系(GCD 同步实现)

    ----------------------------------------------------------------------------------

    NSOperation类是一个抽象类

    特点:

    - 不能直接使用

    目的:

    - 定义子类中共有的属性和方法

    子类:

    - NSInvocationOperation

    - NSBlockOperation

    */

    相关文章

      网友评论

        本文标题:多线程 Nsthread GCD 和 Nsopration 的

        本文链接:https://www.haomeiwen.com/subject/cotbrxtx.html