美文网首页
iOS多线程分析

iOS多线程分析

作者: MoreFish | 来源:发表于2021-04-12 15:58 被阅读0次

    进程

    1.正在进行的一个过程或任务,负责任务执行的是cpu。
    2.每个进程之间是独立的,每个进程都运行在独立的内存空间内,并拥有独立运行所需的全部资源。

    线程

    1.程序运行时的最小单位,是进程的实际运作单位。
    2.进程想要执行任务必须至少有一个线程。在应用程序启动时,系统会默认开启一个线程,即主线程。

    进程和线程的关系

    1.线程在进程下进行
    2.一个进程可以包含多个线程
    3.同一个进程内不同的线程间数据容易共享
    4.进程是用内存地址可以上锁,即一个线程使用共享内存时,其他线程必须等待其结束,才能使用。(互斥锁)
    5.进程使用的内存地址也可以限定使用,即当前只允许2 人访问,第三人需要等待有人结束访问后再进行访问。(信号量)
    6.一个程序有多个进程,一个进程可以有多个线程,但每个进程至少要有一个线程。

    多线程

    1.多条线程并发执行,cpu快速的在多条线程之间调度。 如果cpu调度线程时间足够的快,就造成了多线程并发的假象。
    2.如果线程非常多,也会大量消耗cpu资源。
    3.多线程可以提高程序的执行效率,能适当提高资源的利用率。
    4.如果开启大量的线程会占用内存空间,降低程序性能。

    队列

    串行队列

    同一时间内,队列中只能执行一个任务,当前任务结束后才能执行下一个任务。

    并发队列

    同时允许多个任务并发执行。

    iOS中的多线程

    GCD

    1.获取主线程

    dispatch_queue_t main_queue = dispatch_get_main();
    

    2.线程延时

    /** 
    DISPATCH_TIME_NOW : 现在
    DISPATCH_TIME_FOREVER : 永远超时
    NSEC_PER_SEC : 秒  (1000,000,000 纳秒 = 1秒) 可精确到纳秒级,eg. 0.1 *  NSEC_PER_SEC 是0.1 * 1000,000,000 = 100,000,000 纳秒 = 0.1秒 以下算法雷同。
    NSEC_PER_MSEC : 毫秒 (1000,000 纳秒  = 1 毫秒)可精确到毫秒级
    USEC_PER_SEC : 秒   (1000000微秒 = 1秒) 可精确到微秒级
    NSEC_PER_USEC : 微秒  (1000纳秒 = 1 微秒) 可精确到纳秒级
    */
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), main_queue, ^{
        NSLog(@"哈哈");
    })
    

    3.只执行一次,常用作单例模式

    static dispatch_once_t once;
    dispatch_once(&once, ^{
         // 只实例化一次
         personModel = [[self alloc] init];
     });
    

    4.线程组,即等待一组任务完成后继续执行下一步,常被应用在图片上传

        // 开启全集并发线程,DISPATCH_QUEUE_PRIORITY_DEFAULT 是线程等级, 0 是flag,备用字段,通常设置0
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_async(group, queue, ^{
           // 进行操作1
        });
        dispatch_group_async(group, queue, ^{
           // 进行操作2
        });
        dispatch_group_async(group, queue, ^{
           // 进行操作3
        });
        
        dispatch_group_notify(group, queue, ^{
           // 操作1。2。3 执行完毕 进行 下一步操作
        });
        // 超时等待,即设置一个最长等待时常,超过时间后 调起 notify block
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
    

    5.信号量,设置最大并发线程数,设置数大于1时顺序不能保证

    //创建信号量, 2为设置最大并发线程
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);
        for (int i = 0; i < 5; i++) {
            // 创建异步线程
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                // 信号量的等待时长,这里设置为一直等待,当信号量小于0 时一直等待,如果大于1则进入且降低信号量即-1
                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
                // 睡眠2秒
                sleep(2);
                // po 出当前线程, 显示log
                NSLog(@"%@", [NSThread currentThread]);
                // 标记信号量 + 1
                dispatch_semaphore_signal(semaphore);
                
            });
        }
        
        for (int i = 0; i < 5; i++) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
                sleep(2);
                NSLog(@"%@", [NSThread currentThread]);
                dispatch_semaphore_signal(semaphore);
                
            });
        }
    

    NSOPeration

    NSOperation是基于GCD的抽象基类。
    NSOperation可以跨队列设置依赖关系
    NSOperation面向对象,支持KVO,可以检测operation是否正在执行,是否结束或者取消
    NSOperation实体子类有两个,NSBlockOperation 和 NSInvocationOperation

        // 初始化 方法实例
        NSInvocationOperation *invoOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(haha:) object:nil];
        [invoOperation start];
        // 初始化 block块 实例
        NSBlockOperation *blockOpertaion = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"ni hao ");
        }];
    // 继续添加线程
    blockOperation add
        [blockOpertaion start];
    
        // 以下为 依赖关系
        // 获取 主线程
        NSOperationQueue *main_Operation = [NSOperationQueue mainQueue];
        // 创建 各种线程
        NSOperation *person_a = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"我是 神秘人 A");
        }];
        NSOperation *person_b = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"我是 神秘人 B");
        }];
        NSOperation *person_c = [NSBlockOperation blockOperationWithBlock:^{
            NSLog(@"我是 神秘人 C");
        }];
        // 添加依赖关系, A以来 B和C ,相当于 A要在 B C 之后才能执行任务
        [person_a addDependency:person_b];
        [person_a addDependency:person_c];
        
        //添加到 主线程中 查看顺序
        [main_Operation addOperation:person_a];
        [main_Operation addOperation:person_b];
        [main_Operation addOperation:person_c];
    

    NSThread

    NSThread使用比较简单,可以静态获取线程信息

     // 获取主线程
        NSThread *thread = [NSThread mainThread];
        // 判断是否开启了多线程
        BOOL isOpenThread = [NSThread isMultiThreaded];
        // 获取当前线程
        NSThread *currentThread = [NSThread currentThread];
        // 当前线程睡眠 时间(s) 10秒钟
        [NSThread sleepForTimeInterval:10];
        //  睡眠到指定时间 , 以下为当前时间往后延10秒钟
        [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]];
        // 退出当前线程 , 禁止在主线程使用
        //[NSThread exit];
    
        // 初始化线程对象  实例化对象
        /*
         qualityOfService 线程的优先级
         NSQualityOfServiceUserInteractive 最高级别,用于UI交互,点击事件,绘制图形等
         NSQualityOfServiceUserInitiated = 次高级别,用于执行立即返回的任务
         NSQualityOfServiceUtility 普通级别,不需要立即返回的任务
         NSQualityOfServiceBackground 后台级别,完全不紧急的任务
         NSQualityOfServiceDefault 默认级别
         */
        NSLog(@"%@", [NSThread currentThread]);
        NSThread *asynThread = [[NSThread alloc] initWithTarget:self selector:@selector(hello) object:nil];
        // 设置 线程实例化对象的 优先级别,默认为 默认级别
        asynThread.qualityOfService = NSQualityOfServiceDefault;
        // 开始线程
        [asynThread start];
        
        // 也可以快速创建线程
        [NSThread detachNewThreadSelector:@selector(hello) toTarget:self withObject:nil];
        __weak typeof(self) weakSelf = self;
        [NSThread detachNewThreadWithBlock:^{
            // po 出当前线程
            NSLog(@"%@", [NSThread currentThread]);
            // 回到主线程
            [weakSelf performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
        }];
    
        // 还有一些 创建线程的方法
        // 3 秒后执行 hello 方法 , 在当前线程
        [self performSelector:@selector(hello) withObject:nil afterDelay:3];
        // 后台异步执行
        [self performSelectorInBackground:@selector(hello) withObject:nil];
        // 在主线程上执行 hello 方法
        [self performSelectorOnMainThread:@selector(hello) withObject:nil waitUntilDone:NO];
        // 在 指定的 asynThread 线程上执行 hello方法  *** 注意避免在子线程中执行 ui交互
        [self performSelector:@selector(hello) onThread:asynThread withObject:nil waitUntilDone:NO];
    

    相关文章

      网友评论

          本文标题:iOS多线程分析

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