iOS开发之多线程GCD

前言

iOS开发之多线程理论部分

NSOperation

NSThread

什么是GCD

全称是Grand Central Dispath,纯C语言,提供非常多强大的函数,是目前苹果官网推荐的多线程开发方法,NSOperation便是基于GCD的封装。

GCD的优势所在:

1. 为多核的并行运算提出了解决方案

2. GCD会自动利用更多的CPU内核,比如双核,四核。

3. GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)

4. 程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码



GCD中有2个核心概念

任务:执行什么操作

队列:用来存放任务

队列可以分为两大类型

串行队列(Serial Dispatch Queue):只有一个线程,加入到队列中的操作按添加顺序依次执行,一个任务执行完毕后,才能再执行下一个任务。

并发队列(Concurrent Dispatch Queue):有多个线程,操作进来以后他会将这些线程安排在可用的处理器上,同时保证先进来的任务优先处理。

其实在GCD中还有一个特殊队列就是主队列,用来执行主线程上的操作任务

GCD其实可以抽象为两步

//这是找到了更新UI的主线程所在的队列

dispatch_queue_t mainQueue= dispatch_get_main_queue();

/*

*  创建一个队列

*  第一个参数:队列名字

*  第二个参数:队列类类型

并行队列:DISPATCH_QUEUE_CONCURRENT

串行队列:DISPATCH_QUEUE_SERIAL

*

*/

dispatch_queue_t serialQueue = dispatch_queue_create("mySerialQueue", DISPATCH_QUEUE_SERIAL);

/*

* 系统内部给我们提供有一个现成的并发队列

* 第一个参数:线程的优先级, DISPATCH_QUEUE_PRIORITY_BACKGROUND是最低的。

* 第二个参数:系统保留的参数,永远传0

*/

dispatch_queue_t queue = dispatch_get_global_queue(0 , 0);

2. 在队列中确定想做的事

//在找到的队列中确定想要做的事情,这里我采用的同步方式执行任务,asyn是异步。

dispatch_sync(mainQueue, ^{

});

执行队列中任务的两种方式

用同步的方式执行任务(同步:synchronization),只能在当前线程中执行任务,不具备开启新线程的能力

/*

*  第一个参数:该任务所在的队列

*  第二个参数:该任务要做的事情

*/

dispatch_sync(dispatch_queue_tqueue,dispatch_block_tblock);

假如我指定的队列A是串行队列,则该队列中只能有一个线程,也就是说我放在队列A中的任务,所以必须得一个一个的执行。不仅如此,在上面我们还手动选择了在队列A中用同步的方式执行任务,这也限制了,队列中的任务只能一个一个执行。

假如我指定的队列A是并行队列,则该队列中可以开辟多个线程去执行任务,虽然如此,但由于我们在上面手动选择了在队列A中用同步的方式执行线程,所以队列A中的任务也只能一个一个去执行,不能开辟多线程同时执行

2. 用异步的方式执行任务(异步:asynchronous),可以在新的线程中执行任务,具备开启新线程的能力。

dispatch_async(dispatch_queue_tqueue,dispatch_block_tblock);

假如此时我指定的队列B是并行队列,则表明该队列中可以存在多个线程,又因为我们采用的是异步的方式执行任务,所以在这个队列的任务可以实现同时运行。

假如此时我指定的队列B是串行队列,则表明该队列中,只能有一个线程,所以尽管我采用异步的方式执行任务,但该队列中的任务还是只能一个一个的运行。

GCD创建的线程任务有四种执行方式

1.串行队列同步执行任务

同步不具有开辟新线程的能力,不会开辟新的线程去执行任务,会在当前程序的主线程中执行任务。

按照串行的方式去执行任务

#pragma mark ------------------串行队列同步执行任务--------------dispatch_queue_tserialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);

dispatch_sync(serialQueue, ^{

       NSLog(@"-%@",[NSThreadcurrentThread]);     

    });

dispatch_sync(serialQueue, ^{

        NSLog(@"1 - %@", [NSThreadcurrentThread]);   

  });

dispatch_sync(serialQueue, ^{

      NSLog(@"2 - %@", [NSThreadcurrentThread]);     

});

dispatch_sync(serialQueue, ^{

      NSLog(@"3 - %@", [NSThreadcurrentThread]);      

});

打印结果

2016-03-01 11:44:15.071 GCD[22196:2030750] 1 = {number = 1, name = main}

2016-03-01 11:44:15.071 GCD[22196:2030750] 2 = {number = 1, name = main}

2016-03-01 11:44:15.071 GCD[22196:2030750] 3 = {number = 1, name = main}

2016-03-01 11:44:15.071 GCD[22196:2030750] 4 {number = 1, name = main}



由于是同步操作,不能开辟线程,所以都是在主线程并按照顺序执行

2. 串行队列异步执行任务

异步具有创建新线程的能力,会开辟新的线程去执行任务

按照串行的方式去执行任务

#pragma mark ------------------串行队列异步执行任务------------dispatch_queue_tserialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);

dispatch_async(serialQueue1, ^{

       NSLog(@"1 = %@",[NSThreadcurrentThread]);   

});

dispatch_async(serialQueue1, ^{

    NSLog(@"2 = %@",[NSThreadcurrentThread]);   

});

dispatch_async(serialQueue1, ^{

     NSLog(@"3 = %@",[NSThreadcurrentThread]);   

});

打印结果

2016-03-01 11:56:04.116 GCD[22310:2039747] 1 = {number = 2, name = (null)}

2016-03-01 11:56:04.117 GCD[22310:2039747] 2 = {number = 2, name = (null)}

2016-03-01 11:56:04.118 GCD[22310:2039747] 3 = {number = 2, name = (null)}

因为是异步操作,所以有个编号为2的子线程被开辟,但有因为是串行队列,所以只开辟了一个线程。最终造就了三个线程顺序执行。

3. 并行队列同步执行任务

同步不具有创建新线程的能力,不会开辟新的线程去执行任务,会在当前程序的主线程去执行任务

按照同步的方式去执行任务

虽然并行队列决定了该队列中可以有多个线程,但由于是同步操作,不能开辟线程,所以还都是在主线程中按顺序执行。

4. 并发队列异步执行任务(常用)

异步具有创建新线程的能力,会开辟新的线程去执行任务,不会在当前程序的主线程去执行任务

按照并发的方式去执行任务

dispatch_queue_tconcurrentQueue1 = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(concurrentQueue1, ^{

      NSLog(@"1 = %@",[NSThreadcurrentThread]);   

});

dispatch_async(concurrentQueue1, ^{

      NSLog(@"2 = %@",[NSThreadcurrentThread]);   

});

dispatch_async(concurrentQueue1, ^{

    NSLog(@"3 = %@",[NSThreadcurrentThread]);   

});

打印结果

2016-03-01 14:32:35.880 GCD[22990:2122064] 2 = {number = 3, name = (null)}

2016-03-01 14:32:35.880 GCD[22990:2122063] 1 = {number = 2, name = (null)}

2016-03-01 14:32:35.880 GCD[22990:2122065] 3 = {number = 4, name = (null)}


并行队列可以里可以有多个线程,同步执行的方式又可以开辟多个线程,所以这里实现了多个线程并行执行。

线程锁

没线程锁的情况下:我走进购票大厅,买票的人都没有排队,我好不容易挤到窗口前,正打算掏钱买票的时候,旁边有人已经把钱给了售票员。虽然你的线程已经开始执行买票的方法,但当你去拿票时,也就是将票数减一时,CPU将你的线程给中断,开始执行其他的线程,CPU返回继续执行你的线程的时候,票已经没了。

有线程锁的情况下:*我走进购票大厅,买票的人都在排队,当我到柜台能保证我买票的关键过程,也就是报站、掏钱、拿票过程不受干扰,我采用线程锁将这个关键过程给锁起来,以保证我能顺利的买到票。

你可能感兴趣的:(iOS开发之多线程GCD)