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下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

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