同步:你必须把我的代码执行完你再走,一定要执行完同步里的代码再执行下面的代码
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
异步:你先走执行我下面的代码,我找人、找线程去执行我里面的代码
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
第一步: 创建/获取 队列 第二步: 创建任务,确定要做的事情 第三步: 将任务添加到队列中 (1)GCD会自动将队列中的任务取出,放到对应的线程中执行 (2)任务的取出遵循队列的FIFO原则: 先进先出,后进后出
包括: 串行队列、并发队列、主队列、全局队列
串行队列的特点: 以先进先出的方式,按顺序调度队列中的任务去执行,一次只能调度一个任务。 无论队列中所指定的执行任务的函数是同步还是异步,都必须等待前一个任务执行完毕,才可以调度后面的任务。
串行队列的创建:
(1) dispatch_queue_tqueue = dispatch_queue_create("itheima", DISPATCH_QUEUE_SERIAL);
(2) dispatch_queue_tqueue = dispatch_queue_create("itheima", NULL);
串行队列,同步执行: 开不开线程? 不开线程。 顺序执行还是乱序执行? 顺序执行。
串行队列,异步执行: 开不开线程? 只会开一条线程。 顺序执行还是乱序执行? 顺序执行。
并发队列的创建:
dispatch_queue_t q = dispatch_queue_create("itheima", DISPATCH_QUEUE_CONCURRENT);
并发队列,同步执行: 开不开线程? 不开线程。 顺序执行还是乱序执行? 顺序执行。 并发同步 和 串行同步的执行结果一模一样。
并发队列,异步执行: 开不开线程? 开多条新线程。 顺序执行还是乱序执行? 乱序执行。
- (void)demo1 {
for (int i = 0; i < 10; i++) {
NSLog(@"111");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"hello %d %@",i,[NSThread currentThread]);
});
NSLog(@"222");
NSLog(@"333");
}
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"begin");
for (int i = 0; i < 10; i++) { //死锁,一看同步就不分子线程了,一看主队列,就等着主线程执行完来执行里面代码
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"hello %d %@",i,[NSThread currentThread]);
}); }
NSLog(@"end");
}
先执行begin和end,再顺序执行全局队列异步执行(第二个线程里执行)
- (void)demo3 {
NSLog(@"begin");
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (int i = 0; i < 10; i++) {
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"hello %d %@",i,[NSThread currentThread]); }); }
});
NSLog(@"end");
}
DISPATCH_QUEUE_PRIORITY_HIGH = 2; 高优先级
DISPATCH_QUEUE_PRIORITY_DEFAULT = 0; 默认优先级
DISPATCH_QUEUE_PRIORITY_LOW = -2; 低优先级
DISPATCH_QUEUE_PRIORITY_BACKGROUND = INT16_MIN; 后台优先级
iOS8.0开始,推荐使用服务质量(QOS):
QOS_CLASS_USER_INTERACTIVE = 0x21; 用户交互
QOS_CLASS_USER_INITIATED = 0x19; 用户期望
QOS_CLASS_DEFAULT = 0x15; 默认
QOS_CLASS_UTILITY = 0x11; 实用工具
QOS_CLASS_BACKGROUND = 0x09; 后台
QOS_CLASS_UNSPECIFIED = 0x00; 未指定
通过对比可知: 第一个参数传入0,可以同时适配iOS7及iOS7以后的版本。 服务质量和优先级是一一对应的:
DISPATCH_QUEUE_PRIORITY_HIGH: QOS_CLASS_USER_INITIATED
DISPATCH_QUEUE_PRIORITY_DEFAULT: QOS_CLASS_DEFAULT
DISPATCH_QUEUE_PRIORITY_LOW: QOS_CLASS_UTILITY
DISPATCH_QUEUE_PRIORITY_BACKGROUND: QOS_CLASS_BACKGROUND
dispatch_get_main_queue()
(2)获取全局队列(一种并发队列) dispatch_queue_t 类型
dispatch_get_global_queue(0, 0)
dispatch_queue_t dispatch_get_global_queue(long identifier, unsigned long flags);
dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
例子:创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("hm", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue = dispatch_queue_create("itheima", NULL);
typedef void (^dispatch_block_t)(void);
例子:
dispatch_block_t task = ^{
NSLog(@"hello %@",[NSThread currentThread]);
};
void dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
例子:将任务同步添加到队列和将任务异步添加到队列
(1)dispatch_sync(queue, task);
(2)dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"hello %@",[NSThread currentThread]);
});
void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
_queue = dispatch_queue_create("110", DISPATCH_QUEUE_CONCURRENT);
for (int i = 1; i<=10; i++) {
[self downloadImage:i];}
-(void)downloadImage:(int)index {
dispatch_async(_queue, ^{ //模拟下载图片
NSString *fileName = [NSString stringWithFormat:@"%02d.jpg",index % 10 + 1];
NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
UIImage *img = [UIImage imageWithContentsOfFile:path];
//等待队列中所有的任务执行完成(十个图片下载完成任务),才会执行barrier中的代码
dispatch_barrier_async(_queue, ^{
[self.photoList addObject:img];
NSLog(@"保存图片 %@ %@",fileName,[NSThread currentThread]);
});
NSLog(@"图片下载完成 %@ %@",fileName,[NSThread currentThread]);
});
}
void dispatch_after(dispatch_time_t when,
dispatch_queue_t queue,
dispatch_block_t block);
dispatch_time_t when
多少纳秒之后执行dispatch_time_t dispatch_time(dispatch_time_t when, int64_t delta);
#define DISPATCH_TIME_NOW (0ull)
#define DISPATCH_TIME_FOREVER (~0ull)
#define NSEC_PER_SEC 1000000000ull#define NSEC_PER_MSEC 1000000ull#define USEC_PER_SEC 1000000ull
#define NSEC_PER_USEC 1000ull
dispatch_queue_t queue
任务添加到哪个队列dispatch_block_t block
要执行的任务
用法:延迟1秒后在主队列执行一个任务dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
for (int i = 0; i<20000; i++) {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSLog(@"hello %@",[NSThread currentThread]); });
}
dispatch_group_t group = dispatch_group_create();
(3)监听调度组内队列任务是否执行完毕:把任务添加到队列中,队列添加到调度组中,队列任务执行完毕通知调度组
void dispatch_group_async(dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block);
(4)接收到调度组执行完毕的通知后,执行其它任务
void dispatch_group_notify(dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block);
例子:
//创建组
dispatch_group_t group = dispatch_group_create();
//队列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
//下载第一首歌曲
dispatch_group_async(group, queue, ^{
NSLog(@"正在下载第一个歌曲");
});
//下载第二首歌曲
dispatch_group_async(group, queue, ^{
NSLog(@"正在下载第二个歌曲");
[NSThread sleepForTimeInterval:2.0];
});//下载第三首歌曲dispatch_group_async(group, queue, ^{ NSLog(@"正在下载第三个歌曲");
});
//当三个异步任务都执行完成,才执行dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"over %@",[NSThread currentThread]);
});