一:pthread:基于C
二:NSThread:基于OC
三:GCD:基于C
四:NSOperation:对GCD面向对象的包装
(一):GCD基本操作:六种任务执行模式
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// //创建串行队列
// dispatch_queue_t queue1 = dispatch_queue_create("yhy", DISPATCH_QUEUE_SERIAL);
// //创建并发队列
// dispatch_queue_t queue2 = dispatch_queue_create("yhy", DISPATCH_QUEUE_CONCURRENT);
// //创建主队列(异步函数放在主队列中是不会开线程的,将任务放在主线程中执行)
// dispatch_queue_t queue3 = dispatch_get_main_queue();
// //创建全局队列(全局并发队列)
// dispatch_queue_t queue4 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// //总结:
//同步+并发 == 不能开线程(串行执行任务)
//同步+串行 == 不能开线程(任务串行,在当前线程中执行任务)
//异步+并发 == 可以开线程(开多个线程,任务并行,会开多个线程执行任务)
//异步+串行 == 可以开线程(开一个线程,任务串行,会开一个线程执行任务)
//同步+主队列 == 不能开线程(主线程中执行任务)
//异步+主队列 == 不能开现场(在主线程中执行任务)
//创建线程
// [self synchronizeMain];
// [self synchronizeSerial];
//
// [self synchronizeConcurrent];
//
[self asynchronizeMain];
//
// [self asynchronizeSerial];
//
// [self asynchronizeConcurrent];
}
//下面每一种情况有四个任务
//同步+串行(串行队列派发的任务不需要等待同步函数执行完之后再执行,可以先执行,这就是为什么最后才会执行NSLog(@"以上所有的任务开始执行"))
- (void)synchronizeSerial{
dispatch_queue_t queue = dispatch_queue_create("yhy", DISPATCH_QUEUE_SERIAL);//DISPATCH_QUEUE_SERIAL == null
dispatch_sync(queue, ^{
NSLog(@"1------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"4------%@",[NSThread currentThread]);
});
NSLog(@"以上所有的任务开始执行");
}
//同步+并发(由于并发队列就是全局队列,那么所有的并发队列由全局队列代替,效果和同步+串行一样的)
- (void)synchronizeConcurrent{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(queue, ^{
NSLog(@"1-----%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"2-----%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3-----%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"4-----%@",[NSThread currentThread]);
});
NSLog(@"以上所有的任务开始执行");
}
//同步+主队列(会造成死锁,原有是因为:整个同步函数就是一个任务,但是在主队列中的任务会被调度到主线程中执行,那么这个任务就排在了同步函数这个任务之后,但是主线程中的任务需要一个一个的执行,当执行到主队列派发的任务的时候,这个任务又需要主线程将同步函数这个任务执行完毕之后才能执行,那么主队列派发的任务就不能执行,同步函数这个任务也不能执行,那么就死锁了)
- (void)synchronizeMain{
NSLog(@"dd");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
NSLog(@"1------%@",[NSThread currentThread]);
});
NSLog(@"dd");
dispatch_sync(queue, ^{
NSLog(@"2------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"3------%@",[NSThread currentThread]);
});
dispatch_sync(queue, ^{
NSLog(@"4------%@",[NSThread currentThread]);
});
NSLog(@"以上所有的任务开始执行");
}
//异步+串行(开一条线程,任务在线程中一个一个的执行)
- (void)asynchronizeSerial{
dispatch_queue_t queue = dispatch_queue_create("yhy", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"1------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"4------%@",[NSThread currentThread]);
});
NSLog(@"以上所有的任务开始执行");
}
//异步+并发(开启多条线程,任务在不同的线程中并发执行)
- (void)asynchronizeConcurrent{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSLog(@"1-------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2-------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3-------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"4-------%@",[NSThread currentThread]);
});
NSLog(@"以上所有的任务开始执行");
}
//异步+主队列(不会开线程,在主线程中一个一个的执行)
- (void)asynchronizeMain{
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"1-------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2-------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"3-------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"4-------%@",[NSThread currentThread]);
});
NSLog(@"以上所有的任务开始执行");
}
(二):GCD通信:不同线程之间相互通信
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//将需要耗时的操作放在子线程中,将UI中的图片显示放在主线程中 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:@"http://pic10.nipic.com/20101001/4438138_140843092127_2.jpg"];
NSURL *url1 = [NSURL URLWithString:@"http://e.hiphotos.baidu.com/baike/pic/item/72f082025aafa40f77ca4ed5ab64034f78f019ad.jpg"];
NSData *data1 = [NSData dataWithContentsOfURL:url1];
NSData *data = [NSData dataWithContentsOfURL:url];
//回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = [UIImage imageWithData:data];
self.imageView1.image = [UIImage imageWithData:data1];
});
});
}
(三):GCD中的方法:dispatch_barrier方法
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
for (int i = 0; i < 10; i++) {
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_queue_create("yhy", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"1---------%@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"2---------%@",[NSThread currentThread]);
});
//这个barrier函数就是先让前面所有的任务执行玩之后,再执行它自己,再执行后面的任务,但是queue不能是全局并发队列
dispatch_barrier_sync(queue, ^{
NSLog(@"barrier-----------");
});
dispatch_async(queue, ^{
NSLog(@"3---------%@",[NSThread currentThread]);
}); dispatch_async(queue, ^{
NSLog(@"4---------%@",[NSThread currentThread]);
});
}
NSLog(@"sasfgd");
}
(四):GCD中的方法:dispatch_once方法
//这里没有详细的介绍,今后在swift3中,在面向对象的GCD中再详细介绍
static Person *_person;
+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
//这个方法表面,[super alloc]只会调用一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_person = [super allocWithZone:zone];
});
return _person;
}
(五):GCD:队列组
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//建立组对象
dispatch_group_t group = dispatch_group_create();
//建立队列对象
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//建立队列组
dispatch_group_async(group, queue, ^{
NSURL *url = [NSURL URLWithString:@"http://img1c.xgo-img.com.cn/pics/1717/1716083.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
self.image1 = image;
});
dispatch_group_async(group, queue, ^{
NSURL *url = [NSURL URLWithString:@"http://img1c.xgo-img.com.cn/pics/1717/1716083.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
self.image2 = image;
});
//当队列组中的任务执行完成之后,才会会调用这个方法,这样队列组就避免了获取图形上下文的位图的任务在加载图片的任务之前执行
dispatch_group_notify(group, queue, ^{
//获得图形上下文
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
//绘制图片
[self.image1 drawInRect:CGRectMake(0, 0, 100, 200)];
[self.image2 drawInRect:CGRectMake(100, 0, 100, 200)];
//拿到图形上下文的位图
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
dispatch_async(dispatch_get_main_queue(), ^{
_imageView.image = image;
});
//关闭上下文呢
UIGraphicsEndImageContext();
});
(六):GCD:单例模式
通过GCD实现的单例模式,也就是通过dispatch_once来实现的,将单例抽成宏,给单例的申明和实现取一个别名