gcd这个东西对于开发ios的人应该都听说过,但是很多东西感觉理解起来感觉是有点问题。今天又看了一些关于gcd的东西,现在来说说一些我自己对理解。
我认为gcd最重要的事理解队列,还有同步任务,和异步任务。
首先是队列这个东西,很多人一开始会认为一个队列就是一个线程。这个认知是错误的,队列是什么,其实就是任务的一个集合,一个怎么样的队列决定了你里面的任务是怎么样调度的。
下面是我今天看到一个人对于队列的理解。我感觉十分的透彻。
串行队列:队列里面的任务只能一个一个的调度,比如说你三个下载图片任务,现在你只能一张一张的下载,并不能在后台同时下载三张图片。
并行队列:跟上面相反,可以同时调度三个任务,图片能在后台同时下载。
同步任务:当前指令不完成,无法进行下个指令。
怎么理解这句话,首先我们知道我们的队列都是先进先出的,下面我们来创建一个并行队列,然后同步执行下面的任务
dispatch_queue_t queue=dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);//创建一个并行队列 //同步运行 dispatch_sync(queue, ^{ NSLog(@"11111 %@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"2222 %@" ,[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"3333 %@",[NSThread currentThread]); });
发现了什么问题,虽然是并行队列,意思就是可以调度几个任务的队列,但是执行的时候依然是一个一个的运行,并没有开启新的线程,都还是在主线程运行的。
为什么会造成这样的情况,就是同步任务的原因了。上面说了,同步任务就是当前指令没有执行完,下一条指令不能执行。根据先入先进的原因,我们需要执行的第一句话肯定是打印“1111”.所以这条指令没有执行完成的时候,是不能执行打印@“2222”这条指令的,当我们执行打印@“2222”这条指令的时候,打印“3333”这条指令当然也不能执行。所以即使是并行队列,但是执行的同步任务的话也并不会同时运行几个任务,因为没有必要,你必须执行完上一条指令的时候才能执行下一条。所以即使开启了线程也没用。
异步任务:就是你当前指令即使并没有执行完,你依然能执行下一个指令。
dispatch_queue_t queue=dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);//创建一个并行队列 //异步执行任务 dispatch_async(queue, ^{ NSLog(@"11111 %@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"2222 %@" ,[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3333 %@",[NSThread currentThread]); });
现在就能同时执行三个打印了。而且都在不同的线程执行。
我们现在来继续验证一下这个想法,我们将打印@“1111”设为同步任务,打印“2222”也变成同步任务并睡眠两秒,打印“3333”设为异步任务,来看看会怎么样
dispatch_queue_t queue=dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);//创建一个并行队列 dispatch_sync(queue, ^{ NSLog(@"11111 %@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ [NSThread sleepForTimeInterval:2.0f]; NSLog(@"2222 %@" ,[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"3333 %@",[NSThread currentThread]); });
你会发现,异步任务依然是等到了同步任务都完成之后再执行的。
还有个东西就主队列,在主队列里面进行异步操作会死锁。为什么会这样啦?
因为主队列有个特性,如果主线程里面有任务是不会进行任务的调度的,但是主线程是肯定一直有任务的在运行的,因为主线成需要监视我们是否有UI操作之类的东西,所以不可能主线程有没有任务的时候。所以比如我们平时写的代码都是在主队列中异步操作的。