iOS多线程之GCD

      目前我了解到的多线程编程技术一共有四种,分别是pthread,NSThread,NSOperation,GCD,但在我看来使用最多的还是GCD,今天就先来说说GCD,其他三种请继续关注。。。

     首先,GCD是什么。全称是Grand Central Dispatch,是苹果公司开发的技术,一种底层的纯C语言的API,用来处理多核心处理器和其他对称多处理系统。

     GCD一共有三种队列类型:

 1.The main queue:在程序中向主队列提交的任务会在主线程中执行,通过dispatch_get_main_queue() 来获得,因为是在主线程中完成,所以是串行队列。

 2.global queue : 全局队列是并发队列 。调用dispatch_get_global_queue()来获得,dispatch_get_global_queue()一共需要传两个参数,第一个参数是优先级,优先级分为四种(下面有附),分别是高优先级,默认优先级,低优先级,background(这个目前我还不知道是什么优先级),不过参数一般就按照默认优先级走就OK,第二个参数是flag,目前只支持0和NULL。

#define DISPATCH_QUEUE_PRIORITY_HIGH 2

#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0

#define DISPATCH_QUEUE_PRIORITY_LOW (-2)

#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN


3. 用户队列:通过dispatch_queue_create()来创建队列。

dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);


这里只说说第二参数的 DISPATCH_QUEUE_SERIAL 和  DISPATCH_QUEUE_CONCURRENT


DISPATCH_QUEUE_SERIAL:串行队列,放在此队列中的内容,都是按照FIFO(先进先出)的方式,取出一个来执行一个,也可以理解为多个队列按照排队的方式按照先后顺序一一执行。


DISPATCH_QUEUE_CONCURRENT:并行队列,也是按照FIFO的方式,但是该队列取出一个任务会放到一个线程中,是在不同的线程中执行相应的队列内容,是并发执行的。


注:线程有主线程和子线程之分,用户对UI的操作一定是在主线程上,所以在做加载的时候一定要把线程开到子线程上,才能不影响用户对UI的操作。

//加载图片需要在子线程上,以防阻塞线程造成页面卡死

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ 

        NSURL * backgroundURL = [NSURLURLWithString:backGroundStr];

        NSData * backgroundData = [NSDatadataWithContentsOfURL:backgroundURL];

//更新UI,所以在主线程上

        dispatch_async(dispatch_get_main_queue(), ^{

            imageView.image = [UIImageimageWithData:backgroundData];

        });

    });

        


这里需要和线程的同步和异步执行还有一定的关系,下面列举了不同的情况。

  [self gcdTestMethod:^{

        for (int i = 1; i<5; i++)

        {

            NSString * isMain = [[NSThread currentThreadisMainThread]?@"YES":@"NO";

            NSLog(@"   1====%2d %@ Main:%@",i,[NSThread currentThread],isMain);

        }

    }];

    

    [self gcdTestMethod:^{

        for (int  i = 0; i<5; i++)

        {

            NSString * isMain = [[NSThread currentThreadisMainThread]?@"YES":@"NO";

            NSLog(@"   2=====%2d %@ Main:%@",i,[NSThread currentThread],isMain);

        }

    }];

    


第一种情况:

-(void)gcdTestMethod:(gcdBlockObject)oneGcdobject

{

   if(!_concurrentQ)

   {

     _concurrentQ =dispatch_queue_create(NULL,DISPATCH_QUEUE_SERIAL);

   }

    dispatch_async(_concurrentQ,oneGcdobject);

}

分析:这里的多线程是异步方式,队列是串行队列,所以该队列不会在主线程上,而是在一个新线程上,同时是串行队列,所以排队执行,理论上整个程序是按照哦从上至下的顺序执行,所以第一个for循环会排在前面

执行结果:

2016-01-21 10:42:58.208 多线程_GCD[5366:427771]    1==== 1 <NSThread: 0x7fbf39cabb30>{number = 2, name = (null)} Main:NO

2016-01-21 10:42:58.209 多线程_GCD[5366:427771]    1==== 2 <NSThread: 0x7fbf39cabb30>{number = 2, name = (null)} Main:NO

2016-01-21 10:42:58.209 多线程_GCD[5366:427771]    1==== 3 <NSThread: 0x7fbf39cabb30>{number = 2, name = (null)} Main:NO

2016-01-21 10:42:58.209 多线程_GCD[5366:427771]    1==== 4 <NSThread: 0x7fbf39cabb30>{number = 2, name = (null)} Main:NO

2016-01-21 10:42:58.209 多线程_GCD[5366:427771]    2===== 1 <NSThread: 0x7fbf39cabb30>{number = 2, name = (null)} Main:NO

2016-01-21 10:42:58.210 多线程_GCD[5366:427771]    2===== 2 <NSThread: 0x7fbf39cabb30>{number = 2, name = (null)} Main:NO

2016-01-21 10:42:58.210 多线程_GCD[5366:427771]    2===== 3 <NSThread: 0x7fbf39cabb30>{number = 2, name = (null)} Main:NO

2016-01-21 10:42:58.210 多线程_GCD[5366:427771]    2===== 4 <NSThread: 0x7fbf39cabb30>{number = 2, name = (null)} Main:NO


第二种情况:

-(void)gcdTestMethod:(gcdBlockObject)oneGcdobject

{

 if(!_concurrentQ)

 {

     _concurrentQ =dispatch_queue_create(NULL,DISPATCH_QUEUE_CONCURRENT);

 }

    dispatch_async(_concurrentQ,oneGcdobject);


}

分析:同样是异步线程,但却是同步队列,所以会有两条线程分别执行两个队列,且是同时进行

执行结果:

2016-01-21 10:45:42.653 多线程_GCD[5400:429448]    1==== 1 <NSThread: 0x7fb458c1f240>{number = 3, name = (null)} Main:NO

2016-01-21 10:45:42.653 多线程_GCD[5400:429449]    2===== 1 <NSThread: 0x7fb458e08210>{number = 2, name = (null)} Main:NO

2016-01-21 10:45:42.654 多线程_GCD[5400:429448]    1==== 2 <NSThread: 0x7fb458c1f240>{number = 3, name = (null)} Main:NO

2016-01-21 10:45:42.654 多线程_GCD[5400:429449]    2===== 2 <NSThread: 0x7fb458e08210>{number = 2, name = (null)} Main:NO

2016-01-21 10:45:42.654 多线程_GCD[5400:429448]    1==== 3 <NSThread: 0x7fb458c1f240>{number = 3, name = (null)} Main:NO

2016-01-21 10:45:42.654 多线程_GCD[5400:429449]    2===== 3 <NSThread: 0x7fb458e08210>{number = 2, name = (null)} Main:NO

2016-01-21 10:45:42.655 多线程_GCD[5400:429448]    1==== 4 <NSThread: 0x7fb458c1f240>{number = 3, name = (null)} Main:NO

2016-01-21 10:45:42.655 多线程_GCD[5400:429449]    2===== 4 <NSThread: 0x7fb458e08210>{number = 2, name = (null)} Main:NO


第三种情况:

-(void)gcdTestMethod:(gcdBlockObject)oneGcdobject

{

 if(!_concurrentQ)

 {

     _concurrentQ = dispatch_queue_create(NULLDISPATCH_QUEUE_SERIAL);

 }

    dispatch_sync(_concurrentQ,oneGcdobject);

}


第四种情况:

-(void)gcdTestMethod:(gcdBlockObject)oneGcdobject

{

 if(!_concurrentQ)

 {

     _concurrentQ =dispatch_queue_create(NULL,DISPATCH_QUEUE_CONCURRENT);

 }

    dispatch_sync(_concurrentQ,oneGcdobject);


}

这两种情况一起说一下,因为是在同步线程上,所以是发生在主线程,在执行代码块时就会发生阻塞,等该代码块执行完毕时才会执行下一个代码块,所以不论当前队列是串行还是并行结果都是一样的

2016-01-21 10:47:00.458 多线程_GCD[5440:430735]    1==== 1 <NSThread: 0x7fdfa3e03530>{number = 1, name = main} Main:YES

2016-01-21 10:47:00.459 多线程_GCD[5440:430735]    1==== 2 <NSThread: 0x7fdfa3e03530>{number = 1, name = main} Main:YES

2016-01-21 10:47:00.459 多线程_GCD[5440:430735]    1==== 3 <NSThread: 0x7fdfa3e03530>{number = 1, name = main} Main:YES

2016-01-21 10:47:00.459 多线程_GCD[5440:430735]    1==== 4 <NSThread: 0x7fdfa3e03530>{number = 1, name = main} Main:YES

2016-01-21 10:47:00.459 多线程_GCD[5440:430735]    2===== 1 <NSThread: 0x7fdfa3e03530>{number = 1, name = main} Main:YES

2016-01-21 10:47:00.459 多线程_GCD[5440:430735]    2===== 2 <NSThread: 0x7fdfa3e03530>{number = 1, name = main} Main:YES

2016-01-21 10:47:00.459 多线程_GCD[5440:430735]    2===== 3 <NSThread: 0x7fdfa3e03530>{number = 1, name = main} Main:YES

2016-01-21 10:47:00.460 多线程_GCD[5440:430735]    2===== 4 <NSThread: 0x7fdfa3e03530>{number = 1, name = main} Main:YES


第五种情况:

-(void)gcdTestMethod:(gcdBlockObject)oneGcdobject

{

 // if(!_concurrentQ)

 // {

     _concurrentQ = dispatch_queue_create(NULLDISPATCH_QUEUE_SERIAL);

    NSLog(@"------------");

 // }

    dispatch_async(_concurrentQ,oneGcdobject);

}

分析:这种情况会创建两个队列同时在两个线程上,且这两个线程互不干扰

2016-01-21 11:08:13.943 多线程_GCD[5620:441506] -----------

2016-01-21 11:08:13.943 多线程_GCD[5620:441506] -----------

2016-01-21 11:08:13.943 多线程_GCD[5620:441637]    1==== 1 <NSThread: 0x7fe9aa70a8d0>{number = 2, name = (null)} Main:NO

2016-01-21 11:08:13.944 多线程_GCD[5620:441640]    2===== 1 <NSThread: 0x7fe9aa45d3a0>{number = 3, name = (null)} Main:NO

2016-01-21 11:08:13.944 多线程_GCD[5620:441637]    1==== 2 <NSThread: 0x7fe9aa70a8d0>{number = 2, name = (null)} Main:NO

2016-01-21 11:08:13.944 多线程_GCD[5620:441640]    2===== 2 <NSThread: 0x7fe9aa45d3a0>{number = 3, name = (null)} Main:NO

2016-01-21 11:08:13.945 多线程_GCD[5620:441637]    1==== 3 <NSThread: 0x7fe9aa70a8d0>{number = 2, name = (null)} Main:NO

2016-01-21 11:08:13.945 多线程_GCD[5620:441640]    2===== 3 <NSThread: 0x7fe9aa45d3a0>{number = 3, name = (null)} Main:NO

2016-01-21 11:08:13.945 多线程_GCD[5620:441637]    1==== 4 <NSThread: 0x7fe9aa70a8d0>{number = 2, name = (null)} Main:NO

2016-01-21 11:08:13.946 多线程_GCD[5620:441640]    2===== 4 <NSThread: 0x7fe9aa45d3a0>{number = 3, name = (null)} Main:NO

第六种情况:

-(void)gcdTestMethod:(gcdBlockObject)oneGcdobject

{

// if(!_concurrentQ)

// {

     _concurrentQ = dispatch_queue_create(NULLDISPATCH_QUEUE_CONCURRENT);

    NSLog(@"-----------");

// }

    dispatch_sync(_concurrentQ,oneGcdobject);


}

分析:由于是同步线程,所以必须在主线程上执行完第一个队列上的任务,才会执行下一个

2016-01-21 11:07:26.484 多线程_GCD[5593:440490] -----------

2016-01-21 11:07:26.484 多线程_GCD[5593:440490]    1==== 1 <NSThread: 0x7fe2c1608e60>{number = 1, name = main} Main:YES

2016-01-21 11:07:26.485 多线程_GCD[5593:440490]    1==== 2 <NSThread: 0x7fe2c1608e60>{number = 1, name = main} Main:YES

2016-01-21 11:07:26.485 多线程_GCD[5593:440490]    1==== 3 <NSThread: 0x7fe2c1608e60>{number = 1, name = main} Main:YES

2016-01-21 11:07:26.485 多线程_GCD[5593:440490]    1==== 4 <NSThread: 0x7fe2c1608e60>{number = 1, name = main} Main:YES

2016-01-21 11:07:26.485 多线程_GCD[5593:440490] -----------

2016-01-21 11:07:26.485 多线程_GCD[5593:440490]    2===== 1 <NSThread: 0x7fe2c1608e60>{number = 1, name = main} Main:YES

2016-01-21 11:07:26.485 多线程_GCD[5593:440490]    2===== 2 <NSThread: 0x7fe2c1608e60>{number = 1, name = main} Main:YES

2016-01-21 11:07:26.485 多线程_GCD[5593:440490]    2===== 3 <NSThread: 0x7fe2c1608e60>{number = 1, name = main} Main:YES

2016-01-21 11:07:26.486 多线程_GCD[5593:440490]    2===== 4 <NSThread: 0x7fe2c1608e60>{number = 1, name = main} Main:YES




我也是刚了解,有什么问题再随时补充和修改大笑




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值