[OC学习笔记]浅学GCD线程相关内容
Posted Billy Miracle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[OC学习笔记]浅学GCD线程相关内容相关的知识,希望对你有一定的参考价值。
一、学点基础知识
(一)Queue队列:
Queue队列分为几下几种:
1、全局队列:
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2、主队列:
dispatch_get_main_queue()
3、用户创建的串行队列:
dispatch_queue_create(“com.yuna.com”, DISPATCH_QUEUE_SERIAL/NULL);
4、用户创建的并行队列:
dispatch_queue_create(“com.yuna.com”, DISPATCH_QUEUE_CONCURRENT);
(二)同步与异步
1. 同步
dispatch_sync(queue,block)
:同步队列,dispatch_sync函数不会立即返回,会阻塞当前线程,将block放到指定的queue上面执行,等待该block同步执行完成后才会返回
2. 异步
dispatch_async(queue,block)
:异步队列,dispatch_async函数会立即返回,block放到指定queue中等待执行,该block是并行还是串行只跟queue定义有关
(三)看看组合情况
/*
串行队列 + 同步任务:没有开启新线程,任务是逐个完成的
*/
- (void)serialSync
dispatch_queue_t queue = dispatch_queue_create("com.pi2e.com", DISPATCH_QUEUE_SERIAL);
NSLog(@"串行队列 + 同步----%@",[NSThread currentThread]);
// dispatch_queue_t queue = dispatch_queue_create("com.pi2e.com", NULL);
//在队列里添加同步任务
dispatch_sync(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"---1--%@", [NSThread currentThread]);
);
dispatch_sync(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"---2--%@", [NSThread currentThread]);
);
dispatch_sync(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"---3--%@", [NSThread currentThread]);
);
/*
串行队列 + 异步任务:开启新线程,任务是逐个完成的
*/
- (void)serialAsync
dispatch_queue_t queue = dispatch_queue_create("com.pi2e.com", DISPATCH_QUEUE_SERIAL);
// dispatch_queue_t queue = dispatch_queue_create("com.pi2e.com", NULL);
NSLog(@"串行队列 + 异步----%@",[NSThread currentThread]);
//在队列里添加异步任务
dispatch_async(queue, ^
for(int i = 0; i < 5;i++)
NSLog(@"---1--%@", [NSThread currentThread]);
);
dispatch_async(queue, ^
for(int i = 0; i < 5; i++)
NSLog(@"---2--%@", [NSThread currentThread]);
);
dispatch_async(queue, ^
for(int i = 0; i < 5; i++)
NSLog(@"---3--%@", [NSThread currentThread]);
);
/*
并发队列 + 同步任务 :没有开启新线程,任务是逐个执行
*/
- (void)createConCurrentQueueSyn
//创建并发队列
dispatch_queue_t queue = dispatch_queue_create("com.pi2e.com", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"并发队列 + 同步----%@",[NSThread currentThread]);
//在队列里添加同步任务
dispatch_sync(queue, ^
for (int i = 0 ; i < 5;i++)
NSLog(@"---1--%@",[NSThread currentThread]);
);
dispatch_sync(queue, ^
for (int i=0 ; i < 5;i++)
NSLog(@"---2--%@",[NSThread currentThread]);
);
dispatch_sync(queue, ^
for (int i=0 ; i < 5;i++)
NSLog(@"---3--%@",[NSThread currentThread]);
);
/*
并发队列 + 异步任务 :开启新线程,任务是并发的
*/
- (void)createConCurrentQueueAsyn
dispatch_queue_t queue = dispatch_queue_create("com.pi2e.com", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"并发队列 + 异步----%@", [NSThread currentThread]);
//队列中添加异步任务
dispatch_async(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"--1--%@", [NSThread currentThread]);
);
dispatch_async(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"--2--%@", [NSThread currentThread]);
);
dispatch_async(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"--3--%@", [NSThread currentThread]);
);
/*
全局队列 + 同步任务:,没有开启新线程,任务逐个执行
*/
- (void)GlabolSyc
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"全局队列 + 同步----%@",[NSThread currentThread]);
//在队列里添加同步任务
dispatch_sync(queue, ^
for (int i=0 ; i < 5; i++)
NSLog(@"---1--%@", [NSThread currentThread]);
);
dispatch_sync(queue, ^
for (int i=0 ; i < 5; i++)
NSLog(@"---2--%@", [NSThread currentThread]);
);
dispatch_sync(queue, ^
for (int i=0 ; i < 5; i++)
NSLog(@"---3--%@", [NSThread currentThread]);
);
/*
全局 + 异步:开启新线程,任务是并发的
*/
- (void)GlobalAsync
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"全局队列 + 异步----%@", [NSThread currentThread]);
//队列中添加异步任务
dispatch_async(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"--1--%@", [NSThread currentThread]);
);
dispatch_async(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"--2--%@", [NSThread currentThread]);
);
dispatch_async(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"--3--%@", [NSThread currentThread]);
);
/*
主队列(串行)+同步:界面卡死
主队列中添加同步任务会造成死锁的
*/
//dispatch_sync 是指在指定线程队列queue 同步执行任务block,
//dispatch_sync具有等待block执行结束再能回调的特点;
- (void)mainthreadSync
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"主队列(串行)+同步----%@",[NSThread currentThread]);
//在队列里添加同步任务
dispatch_sync(queue, ^
for (int i = 0; i < 10; i++)
NSLog(@"--1--%@", [NSThread currentThread]);
);
dispatch_sync(queue, ^
for (int i = 0; i < 10; i++)
NSLog(@"--2--%@", [NSThread currentThread]);
);
dispatch_sync(queue, ^
for (int i = 0; i < 10; i++)
NSLog(@"--3--%@", [NSThread currentThread]);
);
/*
主队列(串行)+异步:没有创建新线程,任务逐个完成 {都是在主线程中执行的}
*/
- (void)mainthreadAsync
dispatch_queue_t queue = dispatch_get_main_queue();
NSLog(@"主队列(串行)+异步----%@",[NSThread currentThread]);
//在队列里添加异步任务
dispatch_async(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"--1--%@", [NSThread currentThread]);
);
dispatch_async(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"--2--%@", [NSThread currentThread]);
);
dispatch_async(queue, ^
for (int i = 0; i < 5; i++)
NSLog(@"--3--%@", [NSThread currentThread]);
);
(四)其他
对NSNotificationCenter的分析
- (void)viewDidLoad
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(passValue:) name:@"PassValue" object:nil];
[self sentValue];
NSLog(@"通知赋值完毕");
- (void)sentValue
NSLog(@"发送通知");
NSDictionary *dict = @@"myValue":@"Billy通知传值";
[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"PassValue" object:nil userInfo:dict]];
- (void)passValue:(NSNotification *)text
NSString *valueStr = text.userInfo[@"myValue"];
NSLog(@"收到值:%@",valueStr);
sleep(3);
分析:
通过打印的时间我们可以看出,当我们发送通知以后,观察者在接收到值以后,休眠了3秒,程序才会继续往下执行,也就是说这个过程是同步的;这里面设计为同步,大概是考虑到,一个通知可能有多个监听者,采用同步的方式能够保证所有的观察者都能够对通知做出相应,不会遗漏。
改为异步:
- (void)sentValue
NSLog(@"发送通知");
NSDictionary *dict = @@"myValue":@"Billy通知传值";
dispatch_async(dispatch_get_main_queue(), ^
[[NSNotificationCenter defaultCenter] postNotification:[NSNotification notificationWithName:@"PassValue" object:nil userInfo:dict]];
);
二、看看死锁
先理解几个概念:
(一)串行队列:
任务按照顺序添加在一个队列中,依次执行,常用的串行队列有主队列main queue和一般的串行队列serial queue。
(二)dispatch_sync():
同步任务,即前一个任务执行完毕,后面的任务才会开始执行,否则后面的任务都处于等待状态。
(三)死锁发生的原因:
在同一个串行队列中,如果主队列中的有个执行函数未执行完毕,恰好执行函数中通过dispatch_sync()
添加同步任务,这时就会发生死锁。主队列中添加同步任务会造成死锁。也就是:主队列中的执行函数当前是作为第一个任务正在执行,必须执行完该函数,才算执行完首个任务并返回结果,此时才会向下执行后面的任务,如果此时执行函数中又通过dispatch_sync()
同步添加了newTask,那么执行函数必须等刚添加的newTask执行完,才能向下执行,也就才算执行函数的调用结束,即首个任务执行完毕;而newTask作为同步添加的第二个任务,又在等待首个任务即执行函数执行完,才会开始执行,这样就出现了相互等待的情况,两个任务永远无法执行完,即出现死锁。
(四)例:
- (void)viewDidLoad
[super viewDidLoad];
dispatch_sync(dispatch_get_main_queue(), ^
NSLog(@"newTask");
);
同步对于任务是立刻执行的,那么当把任务放进主队列时,它就会立马执行,只有执行完这个任务,viewDidLoad
才会继续向下执行。而viewDidLoad
和任务都是在主队列上的,由于队列的先进先出原则,任务又需等待viewDidLoad
执行完毕后才能继续执行,viewDidLoad
和这个任务就形成了相互循环等待,就造成了死锁。想避免这种死锁,可以将同步改成异步dispatch_async
,或者将dispatch_get_main_queue
换成其他串行或并行队列,都可以解决。因此,不要用dispatch_sync()
把block压入当前队列。
以上是关于[OC学习笔记]浅学GCD线程相关内容的主要内容,如果未能解决你的问题,请参考以下文章