GCD编程

今天谈论gcd编程的相关知识,gcd编程应该包涵的知识点有:g c d串行队列和并发队列,g c d的延时,线程组,信号量和定时器

gcd串行队列和并发队列

串行队列一次只执行一个线程,按照添加到队列的顺序依次执行。并发队列一次可以执行多个线程,线程的执行没有先后顺序。
注意:ui界面所在的线程队列为串行队列,

可以把gcd队列,gcd线程组,g c d信号源和gcd定时器封装成oc对象的形式。

首先如何理解串行队列

//串行队列
-(void)serailqueue{
    GCDQueue *queue = [[GCDQueue alloc] initSerial];
    
    //执行队列
    [queue execute:^{
        NSLog(@"1");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"2");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"3");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"4");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"5");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"6");
    }];
}

结果表明它是按照顺序执行队列中的线程,输出结果为:1 2 3 4 5 6

如何理解并发队列

//并发队列
-(void)intconcurrent{
    GCDQueue *queue = [[GCDQueue alloc] initConcurrent];
    
    //执行队列
    [queue execute:^{
        NSLog(@"1");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"2");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"3");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"4");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"5");
    }];
    //执行队列
    [queue execute:^{
        NSLog(@"6");
    }];
}

输出结果为:

2016-11-23 14:32:08.107 GCD[7877:288289] 2
2016-11-23 14:32:08.107 GCD[7877:288354] 3
2016-11-23 14:32:08.107 GCD[7877:288290] 1
2016-11-23 14:32:08.107 GCD[7877:288292] 4
2016-11-23 14:32:08.107 GCD[7877:288369] 5
2016-11-23 14:32:08.107 GCD[7877:288289] 6

线程的执行顺序是无法预测的

如何理解ui界面线程所在的队列是串行队列

一般情况下,我们会创建一个默认的线程,用一个下载图片的例子说明

 //初始化imageview
    self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    self.imageView.center = self.view.center;
    [self.view addSubview:self.imageView];
   
    
    
    [GCDQueue executeInGlobalQueue:^{
        //处理业务逻辑
        
        NSString *netURLString = @"";
        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:netURLString]];
        //发起一个同步请求,会阻塞主线程
        NSData *picdata = [NSURLConnection sendSynchronousRequest:request
                                                returningResponse:nil
                                                            error:nil];
        self.image = [UIImage imageWithData:picdata];
        
        [GCDQueue executeInMainQueue:^{
            //更新ui
            self.imageView.image = self.image;
        }];
    }];

GCD延时执行

应该知道nsthread应该也有延时执行的操作,那gcd的延时执行有怎样的优点和缺点
当需要一个等待2s钟的操作,
nsthread的方式:

 //nsthread方式的延时执行操作
    [self performSelector:@selector(threadevent:)
               withObject:self
               afterDelay:2.f];

GCD的方式:

[GCDQueue executeInMainQueue:^{
        NSLog(@"gcd线程事件");
    }
                  afterDelaySecs:2.f];

gcd延时的优点:
1.它可以不用在单独写一个方法执行,写法简单。
gcd的缺点:它不可以取消延时操作,而nsthread可以通过[NSObject cancelPreviousPerformRequestsWithTarget:self];取消延时的操作

GCD线程组

接着谈论gcd线程组有什么用处,在线程组中如何进行事件的监听

如果要实现一个等待线程一和线程2执行完毕后,在去执行线程3.用线程组怎样操作

//初始化一个线程组合
    GCDGroup *group = [[GCDGroup alloc] init];
    
    //创建一个线程队列
    GCDQueue *queue = [[GCDQueue alloc] initConcurrent];
    
    //让线程在group中执行(线程1)
    [queue execute:^{
        sleep(1);
        NSLog(@"线程1执行完毕");
    } inGroup:group];
    
    //让线程在group中执行(线程2)
    [queue execute:^{
        sleep(3);
        NSLog(@"线程2执行完毕");
    } inGroup:group];

    //监听线程组是否执行结束,然后执行线程3
    [queue notify:^{
        NSLog(@"线程3执行完毕");
    } inGroup:group];

GCD定时器

怎样构建一个gcd定时器,它和nstimer创建的定时器有什么区别
首先,创建一个gcd定时器:

//运行gcdtimer
-(void)runGCDTimer{
    //初始化定时器
    self.gcdTimer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
    
    //指定时间间隔以及要执行的事件
    [self.gcdTimer event:^{
        NSLog(@"gcd定时器");
    } timeInterval:NSEC_PER_SEC];
    
    //运行gcd定时器
    [self.gcdTimer start];
}

//运行nastier

//运行nstimer定时器
-(void)runnstimer{
    self.normaltimer = [NSTimer scheduledTimerWithTimeInterval:1.f
                                                        target:self
                                                      selector:@selector(timeevent)
                                                      userInfo:nil
                                                       repeats:YES];
}

-(void)timeevent{
    NSLog(@"nstimer定时器");
}

gcd定时器和nstimer有什么区别:
nastier是作用在当前的runloop里的,如果把nastier用在table中会出现一些奇怪的现象,gcd定时器就不会出现这种情况。

GCD信号量

如何将gcd信号量的使用,以及将异步线程转为同步线程。
首先模拟一种场景,线程1执行完毕之后,然后用线程2执行。
思路:在线程1执行完毕后发送信号,线程2中等待接受信号。

//创建信号量
    GCDSemaphore *semaphore = [[GCDSemaphore alloc] init];
    
    //线程1 - 异步
    [GCDQueue executeInGlobalQueue:^{
        NSLog(@"线程1");
        //发送信号
        [semaphore signal];
        
    }];
    
    //线程2 - 异步
    [GCDQueue executeInGlobalQueue:^{
        NSLog(@"线程2");
        //等待信号
        [semaphore wait];
        
    }];

GCD综合使用

就做一个使用gcd并发下载多张图片

 self.view1 = [self creatImageViewWithFrame:CGRectMake(0, 0, 100, 100)];
    self.view2 = [self creatImageViewWithFrame:CGRectMake(0, 100, 100, 100)];
    self.view3 = [self creatImageViewWithFrame:CGRectMake(0, 200, 100, 100)];
    
    NSString *net1 = @"";
    NSString *net2 = @"";
    NSString *net3 = @"";
    
    [GCDQueue executeInGlobalQueue:^{
        //获取图片
        UIImage *image1 = [self accessdatabynetstring:net1];
        
        [GCDQueue executeInMainQueue:^{
            [UIView animateWithDuration:2.f animations:^{
                self.view1.image = image1;
                self.view1.alpha = 1.0;
            } completion:^(BOOL finished) {
                
            }];
        }];
    }];
    
    [GCDQueue executeInGlobalQueue:^{
        //获取图片
        UIImage *image2 = [self accessdatabynetstring:net2];
        
        [GCDQueue executeInMainQueue:^{
            [UIView animateWithDuration:2.f animations:^{
                self.view2.image = image2;
                self.view2.alpha = 1.0;
            } completion:^(BOOL finished) {
                
            }];
        }];
    }];
    
    [GCDQueue executeInGlobalQueue:^{
        //获取图片
        UIImage *image3 = [self accessdatabynetstring:net3];
        
        [GCDQueue executeInMainQueue:^{
            [UIView animateWithDuration:2.f animations:^{
                self.view3.image = image3;
                self.view3.alpha = 1.0;
            } completion:^(BOOL finished) {
                
            }];
        }];
    }];

截下来做一个顺序显示的图片,借助信号量。

思路:第一张图片加载完之后发一个信号,第二张完成之后在发一个信号,分别在2,3张图片加载时阻塞信号。

self.view1 = [self creatImageViewWithFrame:CGRectMake(0, 0, 100, 100)];
    self.view2 = [self creatImageViewWithFrame:CGRectMake(0, 100, 100, 100)];
    self.view3 = [self creatImageViewWithFrame:CGRectMake(0, 200, 100, 100)];
    
    NSString *net1 = @"";
    NSString *net2 = @"";
    NSString *net3 = @"";
    
    //初始化信号量
    GCDSemaphore *semaphore = [[GCDSemaphore alloc] init];
    
    
    [GCDQueue executeInGlobalQueue:^{
        //获取图片
        UIImage *image1 = [self accessdatabynetstring:net1];
        
        [GCDQueue executeInMainQueue:^{
            [UIView animateWithDuration:2.f animations:^{
                self.view1.image = image1;
                self.view1.alpha = 1.0;
            } completion:^(BOOL finished) {
                //发送信号
                [semaphore signal];
            }];
        }];
    }];
    
    [GCDQueue executeInGlobalQueue:^{
        //获取图片
        UIImage *image2 = [self accessdatabynetstring:net2];
        
        //阻塞
        [semaphore wait];
        
        [GCDQueue executeInMainQueue:^{
            [UIView animateWithDuration:2.f animations:^{
                self.view2.image = image2;
                self.view2.alpha = 1.0;
            } completion:^(BOOL finished) {
                //发送信号
                [semaphore signal];
            }];
        }];
    }];
    
    [GCDQueue executeInGlobalQueue:^{
        //阻塞
        [semaphore wait];
        
        //获取图片
        UIImage *image3 = [self accessdatabynetstring:net3];
        
        [GCDQueue executeInMainQueue:^{
            [UIView animateWithDuration:2.f animations:^{
                self.view3.image = image3;
                self.view3.alpha = 1.0;
            } completion:^(BOOL finished) {
                
            }];
        }];
    }];
}

DEMO下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 今天温故了一下有关 GCD 编程的相关知识,做了个小Demo,梳理一下。其中也是用到在github上下载的别的大牛...
    devZhang阅读 1,134评论 1 9
  • 1. GCD简介 iOS开发中多线程的API主要有pthread,NSThread,NSOperation和GCD...
    安东_Ace阅读 1,246评论 0 6
  • Object C中创建线程的方法是什么?如果在主线程中执行代码,方法是什么?如果想延时执行代码、方法又是什么? 1...
    AlanGe阅读 1,714评论 0 17
  • 畅,我班上的班长,是个阳光明媚的大男孩,性格有些大马哈,但责任心极强,算是班里的顶梁柱、班主任的左膀右臂。 ...
    幸运草的天空阅读 195评论 0 1
  • 大妈一连生了四个女儿,快四十岁时才生了个儿子,自然是宝贝得不得了。所以,从小堂弟便是集万千宠爱于一身,更是在女孩儿...
    了了师太阅读 545评论 6 16