zoukankan      html  css  js  c++  java
  • 多线程

    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可以用同步实现)

  • 相关阅读:
    大话设计模式读书笔记--4.代理模式
    大话设计模式读书笔记--3.装饰模式
    大话设计模式读书笔记--2.策略模式
    大话设计模式读书笔记--1.简单工厂模式
    redis分片
    redis主从同步
    用Jedis连接Redis
    redis的数据类型和指令
    使用可视化工具redisclient连接redis
    《深入浅出通信原理》参考资料
  • 原文地址:https://www.cnblogs.com/sunshineandsand/p/4602178.html
Copyright © 2011-2022 走看看