串行队列
串行队列一次只执行一个线程,按照添加到队列的顺序依次执行
- (void)viewDidLoad {
[self serailQueue];
}
//串行队列
- (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");
}];
}
并发队列
并发队列一次可以执行多个线程,线程的执行没有先后顺序
- (void)viewDidLoad {
[self serailQueue];
}
//并发队列,5个线程同时执行
- (void)initConcurrent{
//创建出了队列
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");
}];
}
UI界面所在的线程队列是串行队列
在子线程中处理业务逻辑,在主线程中更新UI
- (void)viewDidLoad {
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 = @"http://pic.cnitblog.com/avatar/607542/20140226182241.png";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:netUrlString]];
NSData *picData = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil
error:nil];
[GCDQueue executeInMainQueue:^{
//更新UI
self.imageView.image = [[UIImage alloc] initWithData:picData];
}];
}];
}
延时操作
NSThread方式
优点:时间比较精确,而且可以用方法取消。缺点:比较繁琐
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"启动");
//NSThread方式的延时执行操作
[self performSelector:@selector(threadEvent:)
withObject:self
afterDelay:2.f];
//取消延时执行操作
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
- (void)threadEvent:(id)sender{
NSLog(@"线程事件");
}
GCD方式
优点:简单快捷。缺点:时间不够精确,不能取消。
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(@"启动");
//GCD方式的延时执行操作
[GCDQueue executeInMainQueue:^{
NSLog(@"GCD线程事件");
} afterDelaySecs:2.f];
}
GCD线程组(管理线程)
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//初始化线程组合
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定时器
@interface ViewController ()
@property (nonatomic, strong) GCDTimer *timer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.timer = [[GCDTimer alloc] initInQueue:[GCDQueue mainQueue]];
[self.timer event:^{
NSLog(@"GCD定时器");
} timeInterval:NSEC_PER_SEC];
[self.timer start];
}
@end
NSTimer定时器
仅运行在当前runloop? 不能用于tableView?
@interface ViewController ()
@property (nonatomic,strong)NSTimer *normalTimer;
@end
- (void)viewDidLoad {
[super viewDidLoad];
self.normalTimer = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(timerEvent)
userInfo:nil
repeats:YES];
}
- (void)timerEvent{
NSLog(@"NSTimer定时器");
}
GCD信号量- 异步线程转换为同步线程
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//必须线程1先执行完,然后再执行完线程2
//创建信号量, 可以将异步线程转化为同步线程
GCDSemaphore * semaphore = [[GCDSemaphore alloc]init];
//线程1 - 异步
[GCDQueue executeInGlobalQueue:^{
NSLog(@"线程1");
//发送信号
[semaphore signal];
}];
//线程2 - 异步
[GCDQueue executeInGlobalQueue:^{
//等待信号,这时会堵塞住,不会往下执行,直到接收到信号
[semaphore wait];
NSLog(@"线程2");
}];
}
综合使用:采用GCD逐一下载图片
#import "ViewController.h"
#import "GCD.h"
@interface ViewController ()
@property(nonatomic, strong) UIImageView *view1;
@property(nonatomic, strong) UIImageView *view2;
@property(nonatomic, strong) UIImageView *view3;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view1 = [self createImageViewWithFrame:CGRectMake(0, 0, 100, 100)];
self.view2 = [self createImageViewWithFrame:CGRectMake(100, 0, 100, 100)];
self.view3 = [self createImageViewWithFrame:CGRectMake(200, 0, 100, 100)];
NSString *net1 = @"http://pic.cnitblog.com/avatar/607542/20140226182241.png";
NSString *net2 = @"http://pic.cnitblog.com/avatar/708810/20141230105233.png";
NSString *net3 = @"http://pic.cnitblog.com/avatar/704178/20141216150843.png";
//初始化信号量
GCDSemaphore *semaphore = [[GCDSemaphore alloc]init];
//图片1
[GCDQueue executeInGlobalQueue:^{
UIImage *image1 = [self accessDataByNetString:net1];
[GCDQueue executeInMainQueue:^{
[UIView animateWithDuration:2.f animations:^{
self.view1.image = image1;
self.view1.alpha = 1.f;
} completion:^(BOOL finished) {
//发送信号
[semaphore signal];
}];
}];
}];
//图片2
[GCDQueue executeInGlobalQueue:^{
UIImage *image2 = [self accessDataByNetString:net2];
[semaphore wait];
[GCDQueue executeInMainQueue:^{
[UIView animateWithDuration:2.f animations:^{
self.view2.image = image2;
self.view2.alpha = 1.f;
} completion:^(BOOL finished) {
//发送信号
[semaphore signal];
}];
}];
}];
//图片3
[GCDQueue executeInGlobalQueue:^{
UIImage *image3 = [self accessDataByNetString:net3];
[semaphore wait];
[GCDQueue executeInMainQueue:^{
[UIView animateWithDuration:2.f animations:^{
self.view3.image = image3;
self.view3.alpha = 1.f;
} completion:^(BOOL finished) {
//发送信号
[semaphore signal]; }];
}];
}];
}
//创建view
- (UIImageView *)createImageViewWithFrame:(CGRect)frame {
UIImageView *imageView = [[UIImageView alloc]initWithFrame:frame];
imageView.alpha = 0.f;
[self.view addSubview:imageView];
return imageView;
}
//获取网络图片
- (UIImage *)accessDataByNetString:(NSString *)string{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:string]];
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil
error:nil];
return [UIImage imageWithData:data];
}
@end
GCD和NSOperationQueue的区别
- GCD是纯C语言的API,NSOperationQueue是基于GCD的OC版本封装
- GCD只支持FIFO的队列,NSOperationQueue可以很方便的调整执行顺序,设置最大并发数量
- NSOperationQueue可以轻松在Operation间设置依赖关系,而GCD需要写很多的代码才能实现
- NSOperatinQueue支持KVO,可以监测operation是否正在执行(isExecuted),是否结束(isFinished),是否取消(isCanceled)
- GCD的执行速度比NSOperationQueue快
总结:
- 任务之间不太互相依赖:GCD
- 任务之间有依赖\或者要监听任务的执行情况:NSOperationQueue