美文网首页
iOS 多线程再探

iOS 多线程再探

作者: _清墨 | 来源:发表于2022-03-10 11:47 被阅读0次
    一.队列+同步异步

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

    1).串行队列同步执行:任务都在当前线程执行(同步),并且顺序执行(串行)
    2).串行队列异步执行:任务都在开辟的新的子线程中执行(异步),并且顺序执行(串行)
    3).并发队列同步执行:任务都在当前线程执行(同步),但是是顺序执行的(并没有体现并发的特性)
    4).并发队列异步执行:任务在开辟的多个子线程中执行(异步),并且是同时执行的(并发)
    
    -(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);
            });
        });
        
    }
    
    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)}
    
    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是并发队列异步执行,所以他们会在开辟的新线程中并行执行,谁先谁后不一定。符合

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

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

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

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

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

    1.并发队列同步

    -(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.并发队列异步
    我们把代码改成如下:

    -(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.并发队列异步+同步

    -(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.并发队列同步+异步

    -(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执行。

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

    相关文章

      网友评论

          本文标题:iOS 多线程再探

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