//
// ViewController.m
// GSDDemo
//
// Created by Code_Hou on 2017/3/30.
// Copyright © 2017年 侯森魁. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@end
/*
开启新的线程需要占用内存空间:
主线程 在1M左右
每个子线程占用:512KB
*/
@implementation ViewController
- (void)test01{
//1.获取主线程串行队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//2.主线程串行队列同步执行任务,在主线程运行时,会产生死锁
dispatch_sync(mainQueue, ^{
NSLog(@"MainQueue");
});
//程序一直等待状态,block中的代码将执行不到
}
- (void)test02{
//1.获取主线程串行队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//主线程串行队列异步执行、在主线程运行时、不会产生死锁
dispatch_async(mainQueue, ^{
NSLog(@"MainQueue");
});
//程序正常运行,block中的代码正常运行
}
- (void)test03 {
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(globalQueue, ^{
//子线程异步执行下载任务,防止主线程卡顿
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
NSError *error;
NSString *htmlData = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if (htmlData) {
dispatch_queue_t mainQueue = dispatch_get_main_queue();
//异步返回主线程,根据获取的数据,更新UI
dispatch_async(mainQueue, ^{
NSLog(@"更新UI");
});
}else{
NSLog(@"error when downLoad :%@",error);
}
});
/*
主线程串行队列由系统默认生产的,所以无法调用dispatch_resume()和
dispatch_supend()来控制执行继续或中断
*/
}
- (void)test04 {
/*
耗时的操作,比如读取网络数据,IO,数据库读写等,我们会在另外一个线程中处理这些操作,然后通知主线程更新界面
*/
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"Current task 当前线程%@",[NSThread currentThread]);
dispatch_sync(globalQueue, ^{
sleep(10.0);
NSLog(@"sleep 2.0s 当前线程:%@",[NSThread currentThread]);
});
NSLog(@"next task 当前线程:%@",[NSThread currentThread]);
/*
全局并发队列同步执行任务,在主线程执行会导致页面卡顿。哦,因为没有开启新的线程去处理,始终还是在主线程操作
这种写法,我从来没用过,这是什么写法.....我去。。。。。
*/
}
- (void)test05 {
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"Current task 当前线程%@",[NSThread currentThread]);
dispatch_async(globalQueue, ^{
sleep(10.0);
NSLog(@"sleep 10.0s 当前线程:%@",[NSThread currentThread]);
});
NSLog(@"next task 当前线程:%@",[NSThread currentThread]);
/*
全局并发队列异步执行任务,在主线程运行,会开启新的子线程去处理,页面不会kadun
控制台输出:
2017-03-30 09:25:57.384 GSDDemo[1034:37172] Current task 当前线程<NSThread: 0x7ae493a0>{number = 1, name = main}
2017-03-30 09:25:57.385 GSDDemo[1034:37172] next task 当前线程:<NSThread: 0x7ae493a0>{number = 1, name = main}
2017-03-30 09:26:07.459 GSDDemo[1034:37208] sleep 10.0s 当前线程:<NSThread: 0x7c150850>{number = 3, name = (null)}
*/
}
- (void)test06 {
//多个全局并发队列,异步执行任务
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"Current task 当前线程%@",[NSThread currentThread]);
dispatch_async(globalQueue, ^{
NSLog(@"最先加入全局并发队列 当前线程:%@",[NSThread currentThread]);
});
dispatch_async(globalQueue, ^{
NSLog(@"次先加入全局并发队列 当前线程:%@",[NSThread currentThread]);
});
NSLog(@"next task 当前线程:%@",[NSThread currentThread]);
/*
异步线程的执行顺序是不确定的。几乎同步开始执行
全局并发队列由系统默认生成的,所以无法调用dispatch_resume()和dispatch_suspend()来控制执行继续或中断
控制台打印如下:
2017-03-30 09:32:13.148 GSDDemo[1074:41000] Current task 当前线程<NSThread: 0x7ae17820>{number = 1, name = main}
2017-03-30 09:32:13.150 GSDDemo[1074:41034] 次先加入全局并发队列 当前线程:<NSThread: 0x7ae2fc80>{number = 4, name = (null)}
2017-03-30 09:32:13.150 GSDDemo[1074:41033] 最先加入全局并发队列 当前线程:<NSThread: 0x7b920100>{number = 3, name = (null)}
2017-03-30 09:32:13.150 GSDDemo[1074:41000] next task 当前线程:<NSThread: 0x7ae17820>{number = 1, name = main}
*/
}
#pragma mark---自定义队列
- (void)test07 {
//获取自定义串行队列
dispatch_queue_t serialQueue = dispatch_queue_create("com.dullgrass.serialQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"%s",dispatch_queue_get_label(serialQueue));
/*
控制台输出如下:
2017-03-30 09:38:27.626 GSDDemo[1121:43951] com.dullgrass.serialQueue
*/
/*
dispatch_queue_create(<#const char * _Nullable label#>, dispatch_queue_attr_t _Nullable attr)
函数中第一个参数是给这个queue起得标识,这个标识在调试的可以看到是哪个队列在执行,或者在crash日志中,也能做为提示。第二个是需要创建的队列类型,是串行的还是并发的。
*/
}
#pragma mark---自定义串行队列同步执行任务
- (void)test08 {
dispatch_queue_t serialQueue = dispatch_queue_create("com.dullgrass.serialQueue", DISPATCH_QUEUE_SERIAL);
NSLog(@"Current task 当前线程%@",[NSThread currentThread]);
/*
同步操作 没有开启新的线程,那么我用同步线程做什么??
*/
dispatch_sync(serialQueue, ^{
NSLog(@"最先加入自定义的串行队列 当前线程%@",[NSThread currentThread]);
sleep(10);
});
dispatch_sync(serialQueue, ^{
NSLog(@"次先加入自定义的串行队列 当前线程%@",[NSThread currentThread]);
});
NSLog(@"next task 当前线程%@",[NSThread currentThread]);
/*控制台日志:
2017-03-30 09:46:35.191 GSDDemo[1158:48321] Current task 当前线程<NSThread: 0x79656bf0>{number = 1, name = main}
2017-03-30 09:46:35.191 GSDDemo[1158:48321] 最先加入自定义的串行队列 当前线程<NSThread: 0x79656bf0>{number = 1, name = main}
2017-03-30 09:46:45.266 GSDDemo[1158:48321] 次先加入自定义的串行队列 当前线程<NSThread: 0x79656bf0>{number = 1, name = main}
2017-03-30 09:46:45.266 GSDDemo[1158:48321] next task 当前线程<NSThread: 0x79656bf0>{number = 1, name = main}
*/
}
#pragma mark---自定义串行队列同步执行任务,产生死锁
- (void)test09{
dispatch_queue_t serialQueue =dispatch_queue_create("com.dullgrass.SerialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serialQueue, ^{
NSLog(@"会执行的代码 %@",[NSThread currentThread]);
//嵌套同步执行的串行队列卡死在这里
dispatch_sync(serialQueue, ^{
NSLog(@"不会执行的代码 %@",[NSThread currentThread]);
});
});
/*
注意不要嵌套使用同步执行的串行队列
*/
}
#pragma mark---自定义并发队列
- (void)test10{
dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.github.housenkui", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"current task :当前线程%@",[NSThread currentThread]);
dispatch_sync(conCurrentQueue, ^{
NSLog(@"先加入队列 :当前线程%@",[NSThread currentThread]);
});
dispatch_sync(conCurrentQueue, ^{
NSLog(@"后加入队列 :当前线程%@",[NSThread currentThread]);
});
NSLog(@"next task :当前线程%@",[NSThread currentThread]);
/*
控制台日志:
2017-03-30 10:04:58.507 GSDDemo[1304:59257] current task :当前线程<NSThread: 0x7d035800>{number = 1, name = main}
2017-03-30 10:04:58.508 GSDDemo[1304:59257] 先加入队列 :当前线程<NSThread: 0x7d035800>{number = 1, name = main}
2017-03-30 10:04:58.509 GSDDemo[1304:59257] 后加入队列 :当前线程<NSThread: 0x7d035800>{number = 1, name = main}
2017-03-30 10:04:58.509 GSDDemo[1304:59257] next task :当前线程<NSThread: 0x7d035800>{number = 1, name = main}
*/
}
- (void)test11{
dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.githum", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"current task :当前线程%@",[NSThread currentThread]);
dispatch_sync(conCurrentQueue, ^{
NSLog(@"先加入队列 :当前线程%@",[NSThread currentThread]);
dispatch_sync(conCurrentQueue, ^{
NSLog(@"后加入队列 :当前线程%@",[NSThread currentThread]);
});
});
NSLog(@"next task :当前线程%@",[NSThread currentThread]);
/*
控制台输出:
2017-03-30 10:07:54.093 GSDDemo[1326:61314] current task :当前线程<NSThread: 0x7d247130>{number = 1, name = main}
2017-03-30 10:07:54.094 GSDDemo[1326:61314] 先加入队列 :当前线程<NSThread: 0x7d247130>{number = 1, name = main}
2017-03-30 10:07:54.094 GSDDemo[1326:61314] 后加入队列 :当前线程<NSThread: 0x7d247130>{number = 1, name = main}
2017-03-30 10:07:54.094 GSDDemo[1326:61314] next task :当前线程<NSThread: 0x7d247130>{number = 1, name = main}
*/
/*
自定义并发队列嵌套执行同步任务 不会产生死锁,程序正常运行
*/
}
- (void)test12{
dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.github.housenkui", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"current task :当前线程%@",[NSThread currentThread]);
dispatch_async(conCurrentQueue, ^{
NSLog(@"先加入队列 :当前线程%@",[NSThread currentThread]);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"后加入队列 :当前线程%@",[NSThread currentThread]);
});
NSLog(@"next task :当前线程%@",[NSThread currentThread]);
/*
控制台输出:
2017-03-30 10:12:36.946 GSDDemo[1365:64255] current task :当前线程<NSThread: 0x7bf33580>{number = 1, name = main}
2017-03-30 10:12:36.947 GSDDemo[1365:64255] next task :当前线程<NSThread: 0x7bf33580>{number = 1, name = main}
2017-03-30 10:12:36.947 GSDDemo[1365:64294] 先加入队列 :当前线程<NSThread: 0x7d949b40>{number = 3, name = (null)}
2017-03-30 10:12:36.947 GSDDemo[1365:64293] 后加入队列 :当前线程<NSThread: 0x7d9499f0>{number = 4, name = (null)}
*/
/*
异步执行任务,开启新的子线程,不影响当前线程任务的执行,
并发队列中的任务,输出顺序不确定
*/
}
#pragma mark---队列组
/*
当遇到需要执行多个线程并发执行,然后等多个线程结束之后,再汇总执行结果时,可以用group queue
1.使用场景:同时下载多个图片,所有图片下载完之后去,更新UI(回到主线程)或者去处理其他任务
(可以是其他线程队列)
2.原理:使用函数dispatch_group_create 创建dispatch group,然后使用函数dispatch_group_async来将要执行的block任务提交到一个dispatch queue.同时将他们添加到一个组,等要执行的block任务全部执行完成之后,使用dispatch_group_notify 函数接收完成时的消息。
*/
- (void)test13{
dispatch_queue_t conCurrentGlobalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_group_t groupQueue = dispatch_group_create();
NSLog(@"current task 当前线程:%@",[NSThread currentThread]);
dispatch_group_async(groupQueue, conCurrentGlobalQueue, ^{
NSLog(@"并发执行 1 当前线程:%@",[NSThread currentThread]);
});
dispatch_group_async(groupQueue, conCurrentGlobalQueue, ^{
NSLog(@"并发执行2 当前线程:%@",[NSThread currentThread]);
});
dispatch_group_notify(groupQueue, mainQueue, ^{
NSLog(@"groupQueue中的任务都执行完,回到主线程更新UI,当前线程:%@",[NSThread currentThread]);
});
NSLog(@"next task 当前线程:%@",[NSThread currentThread]);
/*控制台日志:
2017-03-30 10:31:58.041 GSDDemo[1469:73285] current task 当前线程:<NSThread: 0x7d1623e0>{number = 1, name = main}
2017-03-30 10:31:58.041 GSDDemo[1469:73345] 并发执行 1 当前线程:<NSThread: 0x7b761330>{number = 3, name = (null)}
2017-03-30 10:31:58.041 GSDDemo[1469:73347] 并发执行2 当前线程:<NSThread: 0x7d1657d0>{number = 4, name = (null)}
2017-03-30 10:31:58.041 GSDDemo[1469:73285] next task 当前线程:<NSThread: 0x7d1623e0>{number = 1, name = main}
2017-03-30 10:31:58.052 GSDDemo[1469:73285] groupQueue中的任务都执行完,回到主线程更新UI,当前线程:<NSThread: 0x7d1623e0>{number = 1, name = main}
*/
}
#pragma mark---在当期线程阻塞的同步等待dispatch_group_wait()
- (void)test14{
dispatch_group_t groupQueue = dispatch_group_create();
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, 10*NSEC_PER_SEC);
dispatch_queue_t conCurrentGlobalQueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"current task 当前线程:%@",[NSThread currentThread]);
dispatch_group_async(groupQueue, conCurrentGlobalQueue, ^{
//isExecuteOver这个值是49 ???
//FIXME:???为甚?
long isExecuteOver = dispatch_group_wait(groupQueue, delayTime);
if (isExecuteOver) {
NSLog(@"wait over当前线程:%@",[NSThread currentThread]);
}
else{
NSLog(@"not over当前线程:%@",[NSThread currentThread]);
}
NSLog(@"并行任务1当前线程:%@",[NSThread currentThread]);
});
dispatch_group_async(groupQueue, conCurrentGlobalQueue, ^{
NSLog(@"并行任务2当前线程:%@",[NSThread currentThread]);
});
/*
控制台日志:
2017-03-30 10:40:21.103 GSDDemo[1504:76995] current task 当前线程:<NSThread: 0x7c14fe60>{number = 1, name = main}
2017-03-30 10:40:21.104 GSDDemo[1504:77028] 并行任务2当前线程:<NSThread: 0x79f6a7f0>{number = 3, name = (null)}
2017-03-30 10:40:31.161 GSDDemo[1504:77026] wait over当前线程:<NSThread: 0x7c155ce0>{number = 4, name = (null)}
2017-03-30 10:40:31.162 GSDDemo[1504:77026] 并行任务1当前线程:<NSThread: 0x7c155ce0>{number = 4, name = (null)}
*/
/*
dispatch_time(dispatch_time_t when,int64_t delta);
参数注释:
第一个参数一般是:DISPATCH_TIME_NOW,表示从现在开始
第二个参数是延时的具体时间:
延时1秒可以写成如下2种:
NSEC_PER_SEC----每秒有多少纳秒
dispatch_time(DISPATCH_TIME_NOW, 1*NSEC_PER_SEC);
USEC_PER_SEC----每秒有多少毫秒(注意是指在纳秒的基础上)
dispatch_time(DISPATCH_TIME_NOW, 1000*USEC_PER_SEC); //SEC---毫秒
*/
}
#pragma mark----dispatch_after
- (void)test15{
dispatch_time_t delayTime3 = dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC);
dispatch_time_t delayTime2 = dispatch_time(DISPATCH_TIME_NOW, 2*NSEC_PER_SEC);
dispatch_queue_t mainQueue = dispatch_get_main_queue();
NSLog(@"curren task");
dispatch_after(delayTime3, mainQueue, ^{
NSLog(@"第3秒之后 添加到队列");
});
dispatch_after(delayTime2, mainQueue, ^{
NSLog(@"第2秒之后 添加到队列");
});
NSLog(@"next task");
/*
控制台打印:
2017-03-30 10:52:59.913 GSDDemo[1616:84429] curren task
2017-03-30 10:52:59.914 GSDDemo[1616:84429] next task
2017-03-30 10:53:02.113 GSDDemo[1616:84429] 第2秒之后 添加到队列
2017-03-30 10:53:03.171 GSDDemo[1616:84429] 第3秒之后 添加到队列
dispatch_after 只是延时提交block ,并不是延迟后执行,并不能做到精确控制。
*/
}
#pragma mark----dispatch_apply
/*
dispatch_apply函数的功能:把一项任务提交到队列中多次执行
*/
- (void)test16{
dispatch_queue_t globalQueue = dispatch_get_global_queue(0, 0);
NSLog(@"current task 当前线程%@",[NSThread currentThread]);
dispatch_async(globalQueue, ^{
dispatch_queue_t applyQueue = dispatch_get_global_queue(0, 0);
/*
第一个参数:3----block的执行次数
第二个参数:applyQueue ----block任务提交到的队列
第三个参数:block----需要重复执行的任务
*/
dispatch_apply(3, applyQueue, ^(size_t index){
NSLog(@"current index %@ 当前线程%@",@(index),[NSThread currentThread]);
sleep(1);
});
NSLog(@"dispatch_apply 执行完成 当前线程%@",[NSThread currentThread]);
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^{
NSLog(@"回到主线程更新UI 当前线程%@",[NSThread currentThread]);
});
});
NSLog(@"next task %@",[NSThread currentThread]);
/*
控制台:
2017-03-30 11:13:02.196 GSDDemo[1683:92762] current task 当前线程<NSThread: 0x7c110b50>{number = 1, name = main}
2017-03-30 11:13:02.197 GSDDemo[1683:92801] current index 1 当前线程<NSThread: 0x7a716720>{number = 3, name = (null)}
2017-03-30 11:13:02.197 GSDDemo[1683:92798] current index 0 当前线程<NSThread: 0x7a627b10>{number = 4, name = (null)}
2017-03-30 11:13:02.197 GSDDemo[1683:92799] current index 2 当前线程<NSThread: 0x7a62b5e0>{number = 5, name = (null)}
2017-03-30 11:13:02.197 GSDDemo[1683:92762] next task <NSThread: 0x7c110b50>{number = 1, name = main}
2017-03-30 11:13:03.198 GSDDemo[1683:92798] dispatch_apply 执行完成 当前线程<NSThread: 0x7a627b10>{number = 4, name = (null)}
2017-03-30 11:13:03.198 GSDDemo[1683:92762] 回到主线程更新UI 当前线程<NSThread: 0x7c110b50>{number = 1, name = main}
嵌套使用dispatch_apply会导致死锁。
*/
}
#pragma mark----dispatch_barrier_async 挡板
/*
功能:是在并行队列中,等待dispatch_barrier_asnc之前加入的队列全部执行完成之后,再执行dispatch_barrier_async的任务,执行完城之后,再去执行在dispatch_barrier_async之后加入到队列中的任务 (这些任务是并发执行的,日志输出的顺序不确定)
*/
- (void)test17{
__block NSData *dataImage;
dispatch_queue_t conCurrentQueue = dispatch_queue_create("com.github.housenkui", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(conCurrentQueue, ^{
NSLog(@"dispatch 1当前线程%@",[NSThread currentThread]);
NSString *loadstring = @"http://pic68.nipic.com/file/20150526/21011915_230134210000_2.jpg";
NSURL *url =[NSURL URLWithString:loadstring];
dataImage = [NSData dataWithContentsOfURL:url];
//让子线程休眠,很少用
sleep(5);
NSLog(@"dispatch 1 sleep 当前线程%@",[NSThread currentThread]);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"dispatch 2当前线程%@",[NSThread currentThread]);
});
dispatch_barrier_async(conCurrentQueue, ^{
NSLog(@"dispatch barrier 当前线程%@",[NSThread currentThread]);
if(dataImage ){
NSLog(@"下载完成");
}
else
{
NSLog(@"没有下载完成");
}
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"dispatch 3当前线程%@",[NSThread currentThread]);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"dispatch 4当前线程%@",[NSThread currentThread]);
});
dispatch_async(conCurrentQueue, ^{
NSLog(@"dispatch 5当前线程%@",[NSThread currentThread]);
});
/*
控制台日志:
2017-03-30 11:32:23.253 GSDDemo[1855:104995] dispatch 2当前线程<NSThread: 0x7c075f70>{number = 4, name = (null)}
2017-03-30 11:32:23.253 GSDDemo[1855:104992] dispatch 1当前线程<NSThread: 0x7c16f580>{number = 3, name = (null)}
2017-03-30 11:32:28.680 GSDDemo[1855:104992] dispatch 1 sleep 当前线程<NSThread: 0x7c16f580>{number = 3, name = (null)}
2017-03-30 11:32:28.681 GSDDemo[1855:104992] dispatch barrier 当前线程<NSThread: 0x7c16f580>{number = 3, name = (null)}
2017-03-30 11:32:28.681 GSDDemo[1855:104992] 下载完成
2017-03-30 11:32:28.682 GSDDemo[1855:104992] dispatch 3当前线程<NSThread: 0x7c16f580>{number = 3, name = (null)}
2017-03-30 11:32:28.682 GSDDemo[1855:104993] dispatch 4当前线程<NSThread: 0x7c264160>{number = 6, name = (null)}
2017-03-30 11:32:28.682 GSDDemo[1855:105041] dispatch 5当前线程<NSThread: 0x7c277990>{number = 7, name = (null)}
*/
}
- (void)viewDidLoad {
[super viewDidLoad];
[self test17];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
GCD 卡塔
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- そよ风が告げる春の访 扫要 卡在 噶 次该路 哈鲁 脑 哦到死来 咲き乱れる花の香りに 撒ki 米大来路 哈那 脑...
- 01 上帝说:“只有那棵能使人辨别善恶的树所结出的果子你们绝对不可吃;你们吃了,当天一定死亡。”但蛇却说:“你们不...
- 前言 Google Play应用市场对于应用的targetSdkVersion有了更为严格的要求。从 2018 年...