iOS多线程

转载请注明出处:http://www.jianshu.com/p/ffd1f7a5db20
作者:纪小衰
参考资料:http://www.cocoachina.com/ios/20160804/17291.html

同步:多个任务情况下,一个任务A执行结束,才可以执行另一个任务B。只存在一个线程也就是主线程。 异步:多个任务情况下,一个任务A正在执行,同时可以执行另一个任务B。任务B不用等待任务A结束才执行。

并行:指两个或多个时间在同一时刻发生。多核CUP同时开启多条线程供多个任务同时执行,互不干扰。 并发:指两个或多个事件在同一时间间隔内发生。可以在某条线程和其他线程之间反复多次进行上下文切换,看上去就好像一个CPU能够并且执行多个线程一样。其实是伪异步。

多线程编程会导致的问题:
1.数据竞争
2.死锁
3.内存消耗和线程切换cpu消耗

使用多线程的必要性: 主线程中会描绘用户界面和处理触摸事件,如果在主线程中进行长事件处理会导致主线程阻塞,妨碍主线程的RunLoop主循环的执行

GCD的使用: 苹果官方对GCD是这样说明的:开发者要做的只是定义想执行的任务并追加到适当的Dispatch Queue中。Dispatch Queue是按照追加的顺序 进行处理,先进先出FIFO。

Serial Dispatch Queue串行调度队列:等待现在执行中的事件处理结束再执行下一个任务。多个串行队列可以并发执行,但是创建多个线程的消耗会比较大,此时考虑使用并行队列

Concurrent Dispatch Queue并发调度队列:不等待现在执行中的事件处理结束就可以开始下一个任务

//创建串行队列
dispatch_queue_t queue1 = dispatch_queue_create("com.jr1", DISPATCH_QUEUE_SERIAL);
//创建并行队列
dispatch_queue_t queue2 = dispatch_queue_create("com.jr1", DISPATCH_QUEUE_CONCURRENT);
//获取系统的主队列 (Main Dispatch Queue是在主线程中执行的Dispatch Queue,也就是Serial Dispatch Queue)
dispatch_queue_t queue3 = dispatch_get_main_queue();
//获取全局队列 (param:优先级,保留字段 type:concurrent)
dispatch_queue_t queue4 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t queue5 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t queue6 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_queue_t queue7 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

//重新设置队列的优先级
dispatch_queue_t newBackQueue = dispatch_queue_create("backQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t backGroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(newBackQueue, backGroundQueue);

//程序执行过程中只执行一次的队列
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    
});

//延迟执行 延迟执行指在多长时间以后追加到队列中,而不是执行
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

});

//3.1串行队列同步执行 输出:1 2 3
dispatch_queue_t q1 = dispatch_queue_create("com.jr1", DISPATCH_QUEUE_SERIAL);
dispatch_async(q1, ^{
    sleep(1);
    NSLog(@"SERIA_ASYNC_1");
});
dispatch_async(q1, ^{
    sleep(0.5);
    NSLog(@"SERIA_ASYNC_2");
});
dispatch_async(q1, ^{
    sleep(0.2);
    NSLog(@"SERIA_ASYNC_3");
});

//3.2串行队列同步执行 输出 :1 2 3
dispatch_queue_t q2 = dispatch_queue_create("com.jr2", DISPATCH_QUEUE_SERIAL);
dispatch_sync(q2, ^{
    sleep(1);
    NSLog(@"SERIAL_SYNC_1");
});
dispatch_sync(q2, ^{
    sleep(0.5);
    NSLog(@"SERIAL_SYNC_2");
});
dispatch_sync(q2, ^{
    sleep(2);
    NSLog(@"SERIAL_SYNC_3");
});


//3.3并行队列异步执行 输出 2 1 4 3
dispatch_queue_t q3 = dispatch_queue_create("com.jr3", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(q3, ^{
    sleep(1);
    NSLog(@"CONCURRENT1");
});
dispatch_async(q3, ^{
    sleep(0.4);
    NSLog(@"CONCURRENT2");
});
dispatch_async(q3, ^{
    sleep(3);
    NSLog(@"CONCURRENT3");
});
dispatch_async(q3, ^{
    sleep(2);
    NSLog(@"CONCURRENT4");
});

//队列组test1  同步任务1 同步任务超时 同步任务2 同步任务完成
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, globalQueue, ^{
    sleep(1);
    NSLog(@"同步任务1");
});
dispatch_group_async(group, globalQueue, ^{
    sleep(4);
    NSLog(@"同步任务2");
});
dispatch_group_notify(group, globalQueue, ^{
    NSLog(@"同步任务完成");
});
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);;
long result = dispatch_group_wait(group, time);
if (result == 0) {
    NSLog(@"任务全部执行完毕");
}else{
    NSLog(@"同步任务超时");
}

//队列组test2 异步任务2 异步任务1 任务结束
dispatch_group_t group2 = dispatch_group_create();
dispatch_queue_t groupQueue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group2, groupQueue2, ^{
    dispatch_group_enter(group2);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"异步任务1");
        dispatch_group_leave(group2);
    });
});
dispatch_group_async(group2, groupQueue2, ^{
    dispatch_group_enter(group2);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSLog(@"异步任务2");
        dispatch_group_leave(group2);
    });
});
dispatch_group_notify(group2, groupQueue2, ^{
    NSLog(@"任务结束");
});
//异步的任务不能使用dispatch_group_wait,因为在闭包中的任务同步部分执行完后任务就结束了,但是dispatch_group_leave还没有调用,所以一定返回任务没有执行成功
dispatch_time_t time2 = dispatch_time(DISPATCH_TIME_NOW, 5*NSEC_PER_SEC);
long result2 = dispatch_group_wait(group2, time2);
if (result2==0) {
    NSLog(@"异步任务成功");
}else{
    NSLog(@"异步任务失败");
}

//提交多个任务 可以实现对于数据的元素并发循环(dispatch_apply为同步返回,阻塞当前线程直到所有的任务结束,如果加入到串行队列,则所有的任务串行执行,如果是并行队列,则所有的任务并发执行。使用并行队列,begin和end不一定成对,数字也不是按照顺序输出,如果使用串行队列,begin和end成对输出,并且数字按照顺序输出)
dispatch_queue_t applyQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t applyQueue2 = dispatch_queue_create("applyQueue", DISPATCH_QUEUE_SERIAL);
dispatch_apply(10, applyQueue2, ^(size_t index) {
    NSLog(@"indexBegin:%ld",index);
    sleep(0.3 * (10 - index));
    NSLog(@"%ld",index);
    NSLog(@"indexEnd:%ld",index);
});
NSLog(@"Apply done");

//队列阻塞 (可解决读者写者的问题)
dispatch_queue_t dbQueue = dispatch_queue_create("dbQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(dbQueue, ^{
    NSLog(@"正在读取1");
    sleep(1);
    NSLog(@"结束读取1");
});
dispatch_async(dbQueue, ^{
    NSLog(@"正在读取2");
    sleep(0.5);
    NSLog(@"结束读取2");
});
dispatch_barrier_sync(dbQueue, ^{
    NSLog(@"正在写入");
    sleep(5);
    NSLog(@"结束写入");
});
dispatch_async(dbQueue, ^{
    NSLog(@"正在读取3");
    sleep(0.5);
    NSLog(@"结束读取3");
});

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

推荐阅读更多精彩内容

  • 本篇博客共分以下几个模块来介绍GCD的相关内容: 多线程相关概念 多线程编程技术的优缺点比较? GCD中的三种队列...
    有梦想的老伯伯阅读 995评论 0 4
  • 欢迎大家指出文章中需要改正或者需要补充的地方,我会及时更新,非常感谢。 一. 多线程基础 1. 进程 进程是指在系...
    xx_cc阅读 7,118评论 11 69
  • .一.进程 进程:是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空...
    IIronMan阅读 4,429评论 1 33
  • 一、前言 上一篇文章iOS多线程浅汇-原理篇中整理了一些有关多线程的基本概念。本篇博文介绍的是iOS中常用的几个多...
    nuclear阅读 1,994评论 6 18
  • 多线程 在iOS开发中为提高程序的运行效率会将比较耗时的操作放在子线程中执行,iOS系统进程默认启动一个主线程,用...
    郭豪豪阅读 2,518评论 0 4