前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS 多线程再探

iOS 多线程再探

作者头像
清墨
发布2022-03-24 08:42:08
1780
发布2022-03-24 08:42:08
举报
文章被收录于专栏:清墨_iOS分享清墨_iOS分享
一.队列+同步异步

关于这个我在前面的文章也写过,这里写个例子复习一下

代码语言:javascript
复制
1).串行队列同步执行:任务都在当前线程执行(同步),并且顺序执行(串行)
2).串行队列异步执行:任务都在开辟的新的子线程中执行(异步),并且顺序执行(串行)
3).并发队列同步执行:任务都在当前线程执行(同步),但是是顺序执行的(并没有体现并发的特性)
4).并发队列异步执行:任务在开辟的多个子线程中执行(异步),并且是同时执行的(并发)
代码语言:javascript
复制
-(void)testCon_queue{
    dispatch_queue_t con_queue = dispatch_queue_create("con", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_async(con_queue, ^{
        dispatch_async(con_queue, ^{
            NSLog(@"1----%@",NSThread.currentThread);
        });
        
        dispatch_sync(con_queue, ^{
            NSLog(@"2----%@",NSThread.currentThread);
        });
        
        dispatch_sync(con_queue, ^{
            NSLog(@"3----%@",NSThread.currentThread);
        });
        
        dispatch_async(con_queue, ^{
            NSLog(@"4----%@",NSThread.currentThread);
        });
        
        dispatch_async(con_queue, ^{
            NSLog(@"5----%@",NSThread.currentThread);
        });
        
        dispatch_async(con_queue, ^{
            NSLog(@"6----%@",NSThread.currentThread);
        });
    });
    
}
代码语言:javascript
复制
1----<NSThread: 0x600001f8d580>{number = 4, name = (null)}
2----<NSThread: 0x600001f98fc0>{number = 3, name = (null)}
3----<NSThread: 0x600001f98fc0>{number = 3, name = (null)}
4----<NSThread: 0x600001f98fc0>{number = 3, name = (null)}
5----<NSThread: 0x600001f98fc0>{number = 3, name = (null)}
6----<NSThread: 0x600001f8d580>{number = 4, name = (null)}
代码语言:javascript
复制
2----<NSThread: 0x6000011af380>{number = 3, name = (null)}
1----<NSThread: 0x6000011aa780>{number = 4, name = (null)}
3----<NSThread: 0x6000011af380>{number = 3, name = (null)}
5----<NSThread: 0x6000011aa780>{number = 4, name = (null)}
6----<NSThread: 0x6000011aa1c0>{number = 5, name = (null)}
4----<NSThread: 0x6000011af380>{number = 3, name = (null)}

解释一下,1 4 5 6是并发队列异步执行,所以他们会在开辟的新线程中并行执行,谁先谁后不一定。符合

代码语言:javascript
复制
4).并发队列异步执行:任务在开辟的多个子线程中执行(异步),并且是同时执行的(并发)

2 3是并发队列同步执行,他们在同一条线程上顺序执行,如结果所示,线程number=3,2了才3。符合

代码语言:javascript
复制
3).并发队列同步执行:任务都在当前线程执行(同步),但是是顺序执行的(并没有体现并发的特性)

我们在上两个结果中也能看见,有异步任务的执行线程跟同步任务执行的线程相同,也有两个异步任务的执行线程相同,这是因为一旦线程任务完成,其他任务可能会复用这条线程,有线程池维护它们,没有必要创建过多的线程造成资源浪费

二.队列+同步异步+信号量

1.并发队列同步

代码语言:javascript
复制
-(void)testSem{
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    dispatch_async(queue, ^{
        NSLog(@"1---%@",NSThread.currentThread);
        
        dispatch_sync(queue, ^{
            [self netWork_task_requestTime:2 completionHandle:^{
                NSLog(@"2---%@",NSThread.currentThread);
                dispatch_semaphore_signal(semaphore);
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"3---%@",NSThread.currentThread);
            
        });
        
        dispatch_sync(queue, ^{
            [self netWork_task_requestTime:1 completionHandle:^{
                NSLog(@"4---%@",NSThread.currentThread);
                dispatch_semaphore_signal(semaphore);
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"5---%@",NSThread.currentThread);
        });
        
        NSLog(@"6---%@",NSThread.currentThread);

    });
}

- (void)netWork_task_requestTime:(int)time completionHandle:(void(^)(void))success {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        success();
    });
}

image.png

解释:信号量初始为0,1输出,执行2后wait,把3和以后的阻塞,2秒后主线程返回,任务完成signal,信号量+1,继续往下执行。 第二个同步任务与第一个执行情况一样:执行4后wait,5和以后的阻塞,1秒后主线程返回,任务完成signal,信号量+1,继续往下执行。 因为是同步执行,所以6最后输出

2.并发队列异步 我们把代码改成如下:

代码语言:javascript
复制
-(void)testSem{
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    dispatch_async(queue, ^{
        NSLog(@"1---%@",NSThread.currentThread);
        
        dispatch_async(queue, ^{
            [self netWork_task_requestTime:2 completionHandle:^{
                NSLog(@"2---%@",NSThread.currentThread);
                dispatch_semaphore_signal(semaphore);
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"3---%@",NSThread.currentThread);
            
        });
        
        dispatch_async(queue, ^{
            [self netWork_task_requestTime:1 completionHandle:^{
                NSLog(@"4---%@",NSThread.currentThread);
                dispatch_semaphore_signal(semaphore);
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"5---%@",NSThread.currentThread);
        });
        
        NSLog(@"6---%@",NSThread.currentThread);

    });
}

image.png

image.png

解释:1 6大家都理解,咱们重点研究4 3 2 5和4 5 2 3 1 6输出后,进入并发异步逻辑,2 4执行,然后3 5被阻塞,4先返回是因为任务4只需1s完成,这时候signal,信号量加一,3和5其中一个可以得到执行,因为是同一并发队列(优先级一样)异步,谁先执行无须在意,但只能执行其中的一个,因为只放出一条可执行线程,然后再过1秒,2完成signal,3 5剩下的一个任务得以执行。

3.并发队列异步+同步

代码语言:javascript
复制
-(void)testSem{
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    dispatch_async(queue, ^{
        NSLog(@"1---%@",NSThread.currentThread);
        
        dispatch_async(queue, ^{
            [self netWork_task_requestTime:2 completionHandle:^{
                NSLog(@"2---%@",NSThread.currentThread);
                dispatch_semaphore_signal(semaphore);
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"3---%@",NSThread.currentThread);
            
        });
        
        dispatch_sync(queue, ^{
            [self netWork_task_requestTime:1 completionHandle:^{
                NSLog(@"4---%@",NSThread.currentThread);
                dispatch_semaphore_signal(semaphore);
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"5---%@",NSThread.currentThread);
        });
        
        NSLog(@"6---%@",NSThread.currentThread);

    });
}

image.png

相信经过上面的讲解,这里大家也很容易明白: 1输出后,2 4得以执行,但3被2阻塞,5 6被4阻塞,然后1秒后,4完成,5得以执行,因为是同步6再得以执行,再过1秒,2完成,3得以执行。

4.并发队列同步+异步

代码语言:javascript
复制
-(void)testSem{
    dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    dispatch_async(queue, ^{
        NSLog(@"1---%@",NSThread.currentThread);
        
        dispatch_sync(queue, ^{
            [self netWork_task_requestTime:2 completionHandle:^{
                NSLog(@"2---%@",NSThread.currentThread);
                dispatch_semaphore_signal(semaphore);
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"3---%@",NSThread.currentThread);
            
        });
        
        dispatch_async(queue, ^{
            [self netWork_task_requestTime:1 completionHandle:^{
                NSLog(@"4---%@",NSThread.currentThread);
                dispatch_semaphore_signal(semaphore);
            }];
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            
            NSLog(@"5---%@",NSThread.currentThread);
        });
        
        NSLog(@"6---%@",NSThread.currentThread);

    });
}

image.png

我想这个结果你已经预料到了: 1执行之后,同步,所以等2秒后2完成,3得以执行,然后是异步,6执行,1秒后4完成,5执行。

总结:只要理解串行并发队列,同步异步,信号量机制,他们的关联使用也是小菜一碟,大家哪点不够明白就攻哪点,各个击破。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022.03.10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.队列+同步异步
  • 二.队列+同步异步+信号量
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档