iOS 多线程再探

一.队列+同步异步

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

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容