iOS 多线程小结

写此文章是为了能够加深自己的记忆,并且对技术点有个记录,方便查阅
这篇文章主要写一些iOS多线程的操作
1.NSThread([θred], 英式发音):轻量级的,编程中很少用,需要自己管理线程,加锁等,很复杂,所以平时编程很少用。
比较常用的是获取当前线程和暂停当前线程
- (void)textAction {
    NSThread *current = [NSThread currentThread];
    NSLog(@"current:%@",current);
    
    [NSThread sleepForTimeInterval:2];
    NSLog(@"finish");
}
2.引自百度百科
Grand Central Dispatch(GCD) 是 Apple 开发的一个多核编程的较新的解决方法。它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统。它是一个在线程池模式的基础上执行的并发任务。在 Mac OS X 10.6 雪豹中首次推出,也可在 iOS 4 及以上版本使用。
GCD有一套完整的api,使用方便,也应该是在实际开发中用的最多的
GCD中有同步(sync)和异步之分(async),串行和并行队列之分
串行队列(Serial Dispatch Queue):
并行队列(Concurrent Dispatch Queue):
GCD自带的两个队列:
//主线程,串行
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//全局队列,并行
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//自定义串行
dispatch_queue_t serialQueue = dispatch_queue_create("com.kevin.abcd", DISPATCH_QUEUE_SERIAL);
//自定义并行
dispatch_queue_t concurrentQueue =dispatch_queue_create("com.kevin.efgh", DISPATCH_QUEUE_CONCURRENT);


dispatch_queue_t queue;
//异步,会开启新线程
dispatch_async(queue, ^{
        //
});
//同步,不会开启新线程
dispatch_sync(queue, ^{
        //
});

用的比较多的其实是主线程刷新ui

    dispatch_async(dispatch_get_main_queue(), ^{
        //
    });
还有任务组,比如需要把两个请求的结果合并为一个,那么可以是两个异步的请求加入dispatch group,等待两个都返回后,调用group的通知,会告知我们任务组里的任务都完成了
    dispatch_queue_t concurrentQueue =dispatch_queue_create("com.kevin.efgh", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, concurrentQueue, ^{
        //执行第一个任务
    });
    dispatch_group_async(group, concurrentQueue, ^{
        //执行第二个任务
    });
    dispatch_group_notify(group, concurrentQueue, ^{
        //group 中的任务执行完
    });
另外需要注意的是在dispatch_group_async中如果执行的是异步操作的话,则notify会失效,需要用
//确保配对使用
        dispatch_group_enter(group);
        dispatch_group_leave(group);
gcd还有许多平常我们经常用的的,例如单利的创建
+(instancetype)sharedInstance \
{ \
static CLASS * sharedInstance = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
sharedInstance = [[CLASS alloc] init]; \
}); \
return sharedInstance; \
}
有时我们需要延迟执行一些操作
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
       // code to be executed after a specified delay
});
如果需要执行两组任务,第一组必须在第二组之前运行,则可以用栅栏函数解决
    dispatch_queue_t concurrentQueueTwo = dispatch_queue_create("com.kevin.concue=rrent", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(concurrentQueue, ^{
        NSLog(@"1");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"2");
    });
    dispatch_barrier_async(concurrentQueue, ^{
        NSLog(@"barrier");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"3");
    });
    dispatch_async(concurrentQueue, ^{
        NSLog(@"4");
    });
gcd还提供线程等待的方法,dispatch_group_wait
gcd中的信号量semaphore([ˈseməfɔ:(r)])
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//创建总数为0的信号
dispatch_semaphore_signal(semaphore);//发送信号,信号+1
dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信号,当信号量少于0时就会一直等待,否则正常执行,并使信号量-1
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//创建总数为0的信号
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"1:%@",[NSThread currentThread]);
//        dispatch_semaphore_signal(semaphore);//发送信号,信号+1
    });
//    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信号,当信号量少于0时就会一直等待,否则正常执行,并使信号量-1
    NSLog(@"5");
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"2:%@",[NSThread currentThread]);
//        dispatch_semaphore_signal(semaphore);//发送信号,信号+1
    });
    NSLog(@"6");
    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"3:%@",[NSThread currentThread]);
//        dispatch_semaphore_signal(semaphore);//+1
    });
    NSLog(@"7");
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"4:%@",[NSThread currentThread]);
//        dispatch_semaphore_signal(semaphore);//+1
    });
//    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
    NSLog(@"end:%@",semaphore);
6后面的不会执行,信号量小于0,输出如下
2018-03-29 17:48:55.679397+0800 TestProject[28407:3448511] 5
2018-03-29 17:48:55.679560+0800 TestProject[28407:3448511] 6
2018-03-29 17:48:57.682849+0800 TestProject[28407:3448635] 2:<NSThread: 0x6040002647c0>{number = 4, name = (null)}
2018-03-29 17:48:57.682849+0800 TestProject[28407:3448618] 1:<NSThread: 0x608000270d80>{number = 3, name = (null)}
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);//创建总数为0的信号,线程数1
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"1:%@",[NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);//发送信号,信号+1
    });
    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);//等待信号,当信号量少于0时就会一直等待,否则正常执行,并使信号量-1
    NSLog(@"5");
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"2:%@",[NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);//发送信号,信号+1
    });
    NSLog(@"6");
    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);

    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"3:%@",[NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);//+1
    });
    NSLog(@"7");
    dispatch_async(queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"4:%@",[NSThread currentThread]);
        dispatch_semaphore_signal(semaphore);//+1
    });
//    dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER);
    NSLog(@"end:%@",semaphore);
会等待1执行完,输出结果如下
2018-03-29 17:53:34.184881+0800 TestProject[28427:3460477] 1:<NSThread: 0x60c000271880>{number = 3, name = (null)}
2018-03-29 17:53:34.185061+0800 TestProject[28427:3460368] 5
2018-03-29 17:53:34.185161+0800 TestProject[28427:3460368] 6
2018-03-29 17:53:36.187280+0800 TestProject[28427:3460477] 2:<NSThread: 0x60c000271880>{number = 3, name = (null)}
2018-03-29 17:53:36.187442+0800 TestProject[28427:3460368] 7
2018-03-29 17:53:36.187581+0800 TestProject[28427:3460368] end:<OS_dispatch_semaphore: 0x60c000091d50>
2018-03-29 17:53:38.190267+0800 TestProject[28427:3460476] 4:<NSThread: 0x60c00026f540>{number = 4, name = (null)}
2018-03-29 17:53:38.190230+0800 TestProject[28427:3460477] 3:<NSThread: 0x60c000271880>{number = 3, name = (null)}

GCD控制并发数量
- (void)testSemaphoreTest{
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);//所开线程数为n+1
    for (int i=0; i<100; ++i) {
        dispatch_async(queue, ^{
            [NSThread sleepForTimeInterval:0.5];
            NSLog(@"number:%d thread:%@",i,[NSThread currentThread]);
            dispatch_semaphore_signal(semaphore);//发送信号,信号+1
        });
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    }
}
3.NSOperation是苹果提供给我们的一套多线程解决方案。比GCD拥有更强的可控性和代码可读性,比如我们想cancel一个任务,控制任务的优先级,用NSOperation就会很方便。
operation queues顾名思义是用来存放operation的队列,可以通过设置最大并发数(maxConcurrentOperationCount)来控制并发,串行。
maxConcurrentOperationCount 默认情况下为-1,表示不进行限制,可进行并发执行。
maxConcurrentOperationCount 为1时,队列为串行队列。只能串行执行
maxConcurrentOperationCount 大于1时,队列为并发队列。操作并发执行,当然这个值不应超过系统限制,即使自己设置一个很大的值,系统也会自动调整为 min{自己设定的值,系统设定的默认最大值}
nsoperation 自带依赖的建立,很方便
-(void)testOperationDependency {
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        //
        NSLog(@"1");
    }];
    
    NSBlockOperation *operationTwo = [NSBlockOperation blockOperationWithBlock:^{
        //
        [NSThread sleepForTimeInterval:5];
        NSLog(@"2");
    }];
    
    NSBlockOperation *operationThree = [NSBlockOperation blockOperationWithBlock:^{
        //
        NSLog(@"3");
    }];
    //1依赖于2的完成
    [operation addDependency:operationTwo];
    
    [queue addOperation:operation];
    [queue addOperation:operationTwo];
    [queue addOperation:operationThree];
    
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容

  • 本文首发于我的个人博客:「程序员充电站」[https://itcharge.cn]文章链接:「传送门」[https...
    ITCharge阅读 347,757评论 308 1,926
  • 1. GCD简介 什么是GCD呢?我们先来看看百度百科的解释简单了解下概念 引自百度百科:Grand Centra...
    千寻_544f阅读 362评论 0 0
  • 本篇博客共分以下几个模块来介绍GCD的相关内容: 多线程相关概念 多线程编程技术的优缺点比较? GCD中的三种队列...
    有梦想的老伯伯阅读 1,020评论 0 4
  • 巴山蜀地,闷热潮湿的夏夜,我关了灯,躺在床上仰望黑灰的天花板。 我住的这家小青旅在22楼,白天的时候,从窗前望出去...
    思寰阅读 281评论 0 0
  • (四) 在阿蒙还回来的书里,多了一张朴素的书签,无名诗人在那上面似乎不经意地写道:当你心中的音乐缓缓响起,那...
    陈士武阅读 97评论 0 0