多线程 GCD
来源:互联网 发布:python 小波变换 编辑:程序博客网 时间:2024/04/28 02:25
CGD 全称 Grand Central Dispatch;
1.全局队列异步执行
- (void)demfor{
//全局队列负责调度任务的
dispatch_queue_tp = dispatch_get_global_queue(0,0);
// 2. 任务 使用block 来包装任务
//block 没有参数,没有返回值
void (^laty)() = ^{
NSLog(@"%@",[NSThreadcurrentThread]);
};
//指定执行执行任务的函数
dispatch_async(p, laty);
//全局队列负责调度任务的
dispatch_queue_tp = dispatch_get_global_queue(0,0);
// 2. 任务 使用block 来包装任务
//block 没有参数,没有返回值
void (^laty)() = ^{
NSLog(@"%@",[NSThreadcurrentThread]);
};
//指定执行执行任务的函数
dispatch_async(p, laty);
}
2. 全局队列同步执行
- (void)demfor1{
//全局队列负责调度任务的
dispatch_queue_tp = dispatch_get_global_queue(0,0);
// 2. 任务 使用block 来包装任务
//block 没有参数,没有返回值
void (^laty)() = ^{
NSLog(@"%@",[NSThreadcurrentThread]);
};
//指定执行执行任务的函数
dispatch_sync(p, laty);
}
小结:
同步不开线程 就在当前线程执行
异步开线程, 在其他线程执行block
//精装版异步
- (void)demfor2{
- (void)demfor2{
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSLog(@"%@",[NSThreadcurrentThread]);
});
}
//精装版同步
- (void)demfor3{
dispatch_sync(dispatch_get_global_queue(0,0), ^{
NSLog(@"%@",[NSThreadcurrentThread]);
});
- (void)demfor3{
dispatch_sync(dispatch_get_global_queue(0,0), ^{
NSLog(@"%@",[NSThreadcurrentThread]);
});
}
三.复用证明
//能够体现出GCD底成是有线程池的
// 一个线程执行完了之后,是可以被复用的
//如果用NSThread需要自己维护线程池,已经管理所有线程的生命周期
//在实际开发中新建线程是一个非常繁琐的工作
- (void)demfor4{
for (int i = 0; i <20; i++) {
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSLog(@"%@",[NSThreadcurrentThread]);
});
}
// 一个线程执行完了之后,是可以被复用的
//如果用NSThread需要自己维护线程池,已经管理所有线程的生命周期
//在实际开发中新建线程是一个非常繁琐的工作
- (void)demfor4{
for (int i = 0; i <20; i++) {
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSLog(@"%@",[NSThreadcurrentThread]);
});
}
}
四.线程间通讯
//线程间通讯
- (void)demfor5{
- (void)demfor5{
dispatch_async(dispatch_get_global_queue(0,0), ^{
// 做耗时的操作
NSLog(@"耗时的操作%@",[NSThreadcurrentThread]);
//通知主线程更新UI
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"更新UI%@",[NSThreadcurrentThread]);
});
});
NSLog(@"耗时的操作%@",[NSThreadcurrentThread]);
//通知主线程更新UI
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"更新UI%@",[NSThreadcurrentThread]);
});
});
}
五.串行队列
串行队列,异步执行
提问:开线程??开几条come
猜测 开,不确定不确定
*/
- (void)demfor7{
//1.参数,队列的名称类似于NSTHread的name属性 是一个C语言的字符串
//2. 队列的属性DISPATCH_QUEUE_CONCURRENT并发队列
//DISPATCH_QUEUE_SERIAL 串行队列
//串行
dispatch_queue_tp = dispatch_queue_create("fjn",DISPATCH_QUEUE_SERIAL);
// 2 执行任务的函数
//10 个异步
for (int i =0; i <10; i++) {
dispatch_async(p, ^{
NSLog(@"%@",[NSThreadcurrentThread]);
});
NSLog(@"fdsfdg");
}
猜测 开,不确定不确定
*/
- (void)demfor7{
//1.参数,队列的名称类似于NSTHread的name属性 是一个C语言的字符串
//2. 队列的属性DISPATCH_QUEUE_CONCURRENT并发队列
//DISPATCH_QUEUE_SERIAL 串行队列
//串行
dispatch_queue_tp = dispatch_queue_create("fjn",DISPATCH_QUEUE_SERIAL);
// 2 执行任务的函数
//10 个异步
for (int i =0; i <10; i++) {
dispatch_async(p, ^{
NSLog(@"%@",[NSThreadcurrentThread]);
});
NSLog(@"fdsfdg");
}
}
六:串行队列
串行队列 同步执行
提问:开线程??开几条come
猜测不开,没有最后
猜测不开,没有最后
*/
(void)demfor7{
//1.参数,队列的名称类似于NSTHread的name属性 是一个C语言的字符串
//2. 队列的属性DISPATCH_QUEUE_CONCURRENT并发队列
//DISPATCH_QUEUE_SERIAL 串行队列
//串行
dispatch_queue_tp = dispatch_queue_create("fjn",DISPATCH_QUEUE_SERIAL);
// 2 执行任务的函数
//10 个异步
for (int i =0; i <10; i++) {
dispatch_sync(p, ^{
NSLog(@"%@",[NSThreadcurrentThread]);
});
NSLog(@"fdsfdg");
}
//1.参数,队列的名称类似于NSTHread的name属性 是一个C语言的字符串
//2. 队列的属性DISPATCH_QUEUE_CONCURRENT并发队列
//DISPATCH_QUEUE_SERIAL 串行队列
//串行
dispatch_queue_tp = dispatch_queue_create("fjn",DISPATCH_QUEUE_SERIAL);
// 2 执行任务的函数
//10 个异步
for (int i =0; i <10; i++) {
dispatch_sync(p, ^{
NSLog(@"%@",[NSThreadcurrentThread]);
});
NSLog(@"fdsfdg");
}
}
七:并行队列
异步任务
//猜测开线程嘛?
//开线程N条线程
//开线程N条线程
//开线程 线程条数由GCD决定
- (void)demfor8{
dispatch_queue_t p = dispatch_queue_create("itchit",DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i <10; i++) {
dispatch_async(p, ^{
NSLog(@"%@ %d",[NSThreadcurrentThread],i);
});
}
dispatch_async(p, ^{
NSLog(@"%@ %d",[NSThreadcurrentThread],i);
});
}
}
八:
并行队列并发队列和串行队列同步执行任务结果一样
同步任务
//猜测开线程嘛?
//不开不开
- (void)demfor9{
dispatch_queue_tp = dispatch_queue_create("itchit",DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i <10; i++) {
dispatch_sync(p, ^{
NSLog(@"%@ %d",[NSThreadcurrentThread],i);
});
}
//不开不开
- (void)demfor9{
dispatch_queue_tp = dispatch_queue_create("itchit",DISPATCH_QUEUE_CONCURRENT);
for (int i = 0; i <10; i++) {
dispatch_sync(p, ^{
NSLog(@"%@ %d",[NSThreadcurrentThread],i);
});
}
}
//阶段性小结:
/**
* 开不开线程 和执行任务的函数有关
- 同步不开
- 异步开
2 (异步)开几条线程和队列有关
- 串行开一条
- 并发开N条具体条数由GCD决定
/**
* 开不开线程 和执行任务的函数有关
- 同步不开
- 异步开
2 (异步)开几条线程和队列有关
- 串行开一条
- 并发开N条具体条数由GCD决定
*/
七:主队列
主队列的概念,只要主队列有任务就不会调度
主队列,异步执行
// 1,队列 - 程序一启动 主线程就已经存在,主队列也同时就存在了,只需要或获取不需要创建
dispatch_queue_tp = dispatch_get_main_queue();
//异步执行
dispatch_async(p, ^{
for (int i = 0; i <10; i++) {
NSLog(@"%@ -- %d",[NSThreadcurrentThread],i);
}
});
NSLog(@"睡会");
[NSThreadsleepForTimeInterval:1];
dispatch_queue_tp = dispatch_get_main_queue();
//异步执行
dispatch_async(p, ^{
for (int i = 0; i <10; i++) {
NSLog(@"%@ -- %d",[NSThreadcurrentThread],i);
}
});
NSLog(@"睡会");
[NSThreadsleepForTimeInterval:1];
NSLog(@"232");
主队列,同步执行
//会造成死锁,因为主队列和同步都在等待
- (void)dowlton1{
dispatch_queue_tp = dispatch_get_main_queue();
//同步执行
dispatch_sync(p, ^{
for (int i = 0; i <10; i++) {
NSLog(@"%@ -- %d",[NSThreadcurrentThread],i);
}
});
- (void)dowlton1{
dispatch_queue_tp = dispatch_get_main_queue();
//同步执行
dispatch_sync(p, ^{
for (int i = 0; i <10; i++) {
NSLog(@"%@ -- %d",[NSThreadcurrentThread],i);
}
});
}
实现同步执行的用处
写一个例子:用户登录 下载A 下载B
要求 必须用户登录成功后,才允许下载
dispatch_queue_t p =dispatch_queue_create("zhujin",DISPATCH_QUEUE_CONCURRENT);
//同步执行任务作用- 作用可以让一些异步执行的任务,依赖,某一个特殊的任务用户登录();
dispatch_sync(p, ^{
NSLog(@"登录%@", [NSThread currentThread]);
});
dispatch_async(p, ^{
NSLog(@"A%@", [NSThreadcurrentThread]);
});
dispatch_async(p, ^{
NSLog(@"b%@", [NSThreadcurrentThread]);
//同步执行任务作用- 作用可以让一些异步执行的任务,依赖,某一个特殊的任务用户登录();
dispatch_sync(p, ^{
NSLog(@"登录%@", [NSThread currentThread]);
});
dispatch_async(p, ^{
NSLog(@"A%@", [NSThreadcurrentThread]);
});
dispatch_async(p, ^{
NSLog(@"b%@", [NSThreadcurrentThread]);
});
}
2.上面的(登录)耗时操作写在了主线程,这明显不行
增强版 block
/提示 通过block 的嵌套,能够让任务非常的负责
//复杂到,很难用一张表格来描述各种组合
//需要理解队列的执行函数的特点
// 同步任务是在当前,没有规定一定在主线程
//队列
dispatch_queue_t p =dispatch_queue_create("zhujin",DISPATCH_QUEUE_CONCURRENT);
void (^ta)() = ^{
//任务
dispatch_sync(p, ^{
NSLog(@"登录%@", [NSThread currentThread]);
});
dispatch_async(p, ^{
NSLog(@"A%@", [NSThreadcurrentThread]);
});
dispatch_async(p, ^{
NSLog(@"b%@", [NSThreadcurrentThread]);
});
//复杂到,很难用一张表格来描述各种组合
//需要理解队列的执行函数的特点
// 同步任务是在当前,没有规定一定在主线程
//队列
dispatch_queue_t p =dispatch_queue_create("zhujin",DISPATCH_QUEUE_CONCURRENT);
void (^ta)() = ^{
//任务
dispatch_sync(p, ^{
NSLog(@"登录%@", [NSThread currentThread]);
});
dispatch_async(p, ^{
NSLog(@"A%@", [NSThreadcurrentThread]);
});
dispatch_async(p, ^{
NSLog(@"b%@", [NSThreadcurrentThread]);
});
};
//异步执行ta
dispatch_async(p, ta);
//异步执行ta
dispatch_async(p, ta);
}
3.主队列同步任务不死锁的操作
- (void)tofds2{
dispatch_queue_t p =dispatch_queue_create("zhujin",DISPATCH_QUEUE_CONCURRENT);
void(^ta)() = ^{
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"com,here %@",[NSThreadcurrentThread]);
});
NSLog(@"hahah,%@",[NSThreadcurrentThread]);
};
dispatch_queue_t p =dispatch_queue_create("zhujin",DISPATCH_QUEUE_CONCURRENT);
void(^ta)() = ^{
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"com,here %@",[NSThreadcurrentThread]);
});
NSLog(@"hahah,%@",[NSThreadcurrentThread]);
};
dispatch_async(p, ta);
}
八.全局队列队列和串行队列的选择
八.全局队列队列和并行队列的选择
九.延迟的操作和参数讲解
9.一次性执行代码
一次性执行->有时候,在程序开发是,会希望一部分代码,从程序启动后,只会被执行一次
最常用的一个场景,单列:在内存中只有唯一的一个副本
- (void)once{
//dispatch_once_t能够保证block中的嗲吗,只会被执行一次
//oncetoken == 0 就是执行block的代码
// dispatch_once是线程安全的
// 只要涉及到线程安全,就会涉及到锁,dispatch_once内部也有不把锁,性能会比互斥锁高
static dispatch_once_t onceToken;
//block 是同步的
//能够保证后续的代码直接使用 block 执行后的结果
dispatch_once(&onceToken, ^{
要执行一次的代码
NSLog(@"是一次嘛?%@",[NSThreadcurrentThread]);
});
}
//判断同步/异步 小技巧
NSLog(@"come here");
MArk 调度组
/**
目的:为了后续网络功能的一个扩展,AFN框架(有名的网络框架)
*/
// The dispatch_group_async() convenience function behaves like so:
// dispatch_group_async()是一个方便的函数,类似于以下代码
/**
void dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block)
{
dispatch_retain(group);
dispatch_group_enter(group);
dispatch_async(queue, ^{
block();
dispatch_group_leave(group);
dispatch_release(group);
});
}
*/
// 知道就行!
- (void)group2 {
// 1. 群组-统一监控一组任务
dispatch_group_tgroup = dispatch_group_create();
dispatch_queue_tq = dispatch_get_global_queue(0,0);
// 1> 入组 -> 之后的 block 会被 group 监听
// dispatch_group_enter一定和 dispatch_group_leave 要配对出现
dispatch_group_enter(group);
dispatch_async(q, ^{
NSLog(@"task1 %@", [NSThreadcurrentThread]);
// block的末尾,所有任务执行完毕后,添加一个出组
dispatch_group_leave(group);
});
// 2> 再次入组
dispatch_group_enter(group);
dispatch_async(q, ^{
[NSThreadsleepForTimeInterval:1.0];
NSLog(@"task2 %@", [NSThreadcurrentThread]);
// block的末尾,所有任务执行完毕后,添加一个出组
dispatch_group_leave(group);
});
// 3. 群组结束
dispatch_group_notify(group,dispatch_get_main_queue(), ^{
NSLog(@"OVER");
});
// 4. 群组等待 -> 等到永远,死等,等到所有任务完成
// 阻塞式的等待,群组任务不执行完,后续代码无法执行!
// 行(知道就)
// dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"come here");
}
// MARK: 调度组
// 应用场景:需要在所有异步任务执行完毕后,统一获得一个通知!
// 新浪微博提前将所有的缩略图(2k~3k)下载到本地,统一刷新表格,就可以针对不同的图片宽高设计UI
// 如果图片在服务器上,是无法直接获得宽高
- (void)group1 {
// 1. 群组-统一监控一组任务
dispatch_group_tgroup = dispatch_group_create();
dispatch_queue_tq = dispatch_get_global_queue(0,0);
// 2. 添加任务
// group 负责监控任务,queue 负责调度任务
dispatch_group_async(group, q, ^{
[NSThreadsleepForTimeInterval:1.0];
NSLog(@"任务1 %@", [NSThreadcurrentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任务2 %@", [NSThreadcurrentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任务3 %@", [NSThreadcurrentThread]);
});
// 3. 监听所有任务完成 -等到 group 中的所有任务执行完毕后,"由队列调度block 中的任务异步执行!"
dispatch_group_notify(group,dispatch_get_main_queue(), ^{
// 修改为主队列,后台批量下载,结束后,主线程统一更新UI
NSLog(@"OK %@", [NSThreadcurrentThread]);
});
NSLog(@"come here");
目的:为了后续网络功能的一个扩展,AFN框架(有名的网络框架)
*/
// The dispatch_group_async() convenience function behaves like so:
// dispatch_group_async()是一个方便的函数,类似于以下代码
/**
void dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block)
{
dispatch_retain(group);
dispatch_group_enter(group);
dispatch_async(queue, ^{
block();
dispatch_group_leave(group);
dispatch_release(group);
});
}
*/
// 知道就行!
- (void)group2 {
// 1. 群组-统一监控一组任务
dispatch_group_tgroup = dispatch_group_create();
dispatch_queue_tq = dispatch_get_global_queue(0,0);
// 1> 入组 -> 之后的 block 会被 group 监听
// dispatch_group_enter一定和 dispatch_group_leave 要配对出现
dispatch_group_enter(group);
dispatch_async(q, ^{
NSLog(@"task1 %@", [NSThreadcurrentThread]);
// block的末尾,所有任务执行完毕后,添加一个出组
dispatch_group_leave(group);
});
// 2> 再次入组
dispatch_group_enter(group);
dispatch_async(q, ^{
[NSThreadsleepForTimeInterval:1.0];
NSLog(@"task2 %@", [NSThreadcurrentThread]);
// block的末尾,所有任务执行完毕后,添加一个出组
dispatch_group_leave(group);
});
// 3. 群组结束
dispatch_group_notify(group,dispatch_get_main_queue(), ^{
NSLog(@"OVER");
});
// 4. 群组等待 -> 等到永远,死等,等到所有任务完成
// 阻塞式的等待,群组任务不执行完,后续代码无法执行!
// 行(知道就)
// dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"come here");
}
// MARK: 调度组
// 应用场景:需要在所有异步任务执行完毕后,统一获得一个通知!
// 新浪微博提前将所有的缩略图(2k~3k)下载到本地,统一刷新表格,就可以针对不同的图片宽高设计UI
// 如果图片在服务器上,是无法直接获得宽高
- (void)group1 {
// 1. 群组-统一监控一组任务
dispatch_group_tgroup = dispatch_group_create();
dispatch_queue_tq = dispatch_get_global_queue(0,0);
// 2. 添加任务
// group 负责监控任务,queue 负责调度任务
dispatch_group_async(group, q, ^{
[NSThreadsleepForTimeInterval:1.0];
NSLog(@"任务1 %@", [NSThreadcurrentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任务2 %@", [NSThreadcurrentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任务3 %@", [NSThreadcurrentThread]);
});
// 3. 监听所有任务完成 -等到 group 中的所有任务执行完毕后,"由队列调度block 中的任务异步执行!"
dispatch_group_notify(group,dispatch_get_main_queue(), ^{
// 修改为主队列,后台批量下载,结束后,主线程统一更新UI
NSLog(@"OK %@", [NSThreadcurrentThread]);
});
NSLog(@"come here");
}
0 0
- GCD多线程
- 多线程GCD
- GCD多线程
- 多线程-GCD
- 多线程 gcd
- 多线程GCD
- 多线程&GCD
- GCD多线程
- 多线程GCD
- 多线程:GCD
- 多线程-GCD
- 多线程GCD
- 多线程-GCD
- GCD(多线程)
- 多线程GCD
- 多线程GCD
- 多线程 GCD
- 多线程GCD
- 区间调度问题
- 遗传算法入门(二)
- 多线程 NSTread
- 第十二周项目二 (3)计算图G中出度为0的顶点数
- zzoffer调整数组顺序使奇数位于偶数前面
- 多线程 GCD
- 前端入门方法总结
- 简单的求和
- poj 2516 Minimum Cost(最小费用最大流 spfa算法求最短路)
- gcc 编译器中 printf i++ 和 ++i 的输出
- Romberg(龙贝格)求积公式求解数值积分时的注意事项
- 单链表的实现
- Linux Advance--线程和fork
- 1093. Count PAT's (25)