iOS多线程GCD篇iOS学习首页投稿(暂停使用,暂停投稿)

GCD编程

2016-11-26  本文已影响103人  shineDeveloper

今天谈论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下载

上一篇下一篇

猜你喜欢

热点阅读