1、概念数组
一、同步异步:
a、同步 dispatch_sync():同步执行会等待当前任务执行完再向下执行
b、异步 dispatch_async():不等待当前任务执行完,而是把任务提交后直接向下执行,不等待提交的任务并发
二、队列
a、串行队列:提交到串行队列的任务会一个一个按顺序执行,上一个任务完成后、再执行下一个
建立方式(2种同样):
一、dispatch_queue_create("tongbu", NULL)
二、dispatch_queue_create("tongbu", DISPATCH_QUEUE_SERIAL);
参数1:队列标签 参数2:队列类型(并发)
三、dispatch_get_main_queue() 主队列也是串行队列
b、并发队列:提交到并发队列的任务对并发执行,每一个任务从提交的那一时刻起都会为它建立一个线
程,且没法肯定哪个任务先完成。
建立方式(2种同样):
一、dispatch_get_global_queue(0, 0)//获取系统的全局并发队列
其中,参数1 有如下可选
DISPATCH_QUEUE_PRIORITY_HIGH //2
DISPATCH_QUEUE_PRIORITY_DEFAULT //0 通常选这个便可
DISPATCH_QUEUE_PRIORITY_LOW //-2
DISPATCH_QUEUE_PRIORITY_BACKGROUND // INT16_MIN ( -32768)
二、dispatch_queue_create("tongbu", DISPATCH_QUEUE_CONCURRENT)//本身建立
参数1:队列标签 参数2:队列类型(并发)
特别提醒:dispatch_queue_create 每执行一次就会建立一个新对象,
dispatch_queue_t queue1 = dispatch_queue_create("tongbu", NULL);
dispatch_queue_t queue2= dispatch_queue_create("tongbu", NULL);
此时queue1 != queue2
因此使用时若是想要使用同一队列,必定要将其存储起来
!并发队列 执行时,并不必定会将添加到队列的任务所有一块儿执行,而是处理数量取决于系统的状态(CPU核数,负载。。)先执行前几个,好比一次性添加了10000个任务到并发队列,他可能因为负载缘由只并发执行了第40个,当根据执行状况再并发后续任务app
2、使用
同步异步与队列结合使用异步
连续添加十个任务
组合1:同步 + 串行
无心义,连续添加十个任务,会加一个执行一个,第一个执行完,执行加入第二个
组合2:异步 + 串行
十个任务是按顺序添加,可是因为是异步添加,不会影响 "结束"的执行,同时,队列时串行队列,因此会挨个执行
组合3:同步 + 并发
无心义,觉得他会等待添加的任务完成在继续下一步
组合4:异步 + 并发
每一个任务都会开启新线程去并发执行,至关因而个任务同时并发执行,且不会阻塞当前程序async
3、函数方法
一、 dispatch_barrier_async函数
dispatch_queue_t queue = dispatch_queue_create("tongbu", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, readFile); dispatch_async(queue, readFile); //会等上面提交的任务完成后再去写,写完后才继续执行下面的提交任务,防止了读写竞争 dispatch_barrier_async(queue, writeFile); dispatch_async(queue, readFile); dispatch_async(queue, readFile);
这样,多个read不会互相影响,提升了读性能,且不影响写操做(注意上面的是并发队列)性能
二、挂起/恢复
注意:它的原理相似于引用计数,一个queue若是调用N次dispatch_suspend,那么要想恢复,就须要调用N次dispatch_resume才能够继续,并且dispatch_resume函数不能随意调用,只有当前队列被挂起后才能够对它使用该函数,不然会报错spa
dispatch_queue_t queue = dispatch_queue_create("tongbu", NULL); dispatch_suspend(queue);//挂起队列 dispatch_resume(queue);//恢复队列
三、定时器线程
//dispatchQueue:该定时器任务在哪一个队列执行 //intervalInSeconds: 间隔时间 //leewayInSeconds :设置为0便可 dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, <#dispatchQueue#>); dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, <#intervalInSeconds#> * NSEC_PER_SEC, <#leewayInSeconds#> * NSEC_PER_SEC); dispatch_source_set_event_handler(timer, ^{ //do something ... }); //一次暂停对应一次开始,默认建立完成timer时是暂停的,原理见上一节 //开始(不暂停时不能随意调用) dispatch_resume(timer); //暂停 dispatch_suspend(timer); //销毁 dispatch_source_cancel(_timer);
须要注意:要持有 timer 和 queue,不能让其销毁,不然定时器失效。
四、dispatch_semaphore_t 信号量
异步的向数组中添加对象会产生内存问题,须要进行锁处理,可使用dispatch_semaphore_t信号量机制实现code
- (void)test1 { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);//并发队列 NSMutableArray *array = [[NSMutableArray alloc] init]; for (int i = 0; i < 10000; ++i) { dispatch_async(queue, ^{ [array addObject:[NSNumber numberWithInteger:i]];//这里会产生内存问题 }); } NSLog(@"完成"); }
使用dispatch_semaphore_t
- (void)test2 { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); NSMutableArray *array = [[NSMutableArray alloc] init]; //信号量 dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); for (int i = 0; i < 10000; ++i) { dispatch_async(queue, ^{ //一、该函数会阻塞,等待直到semaphore计数 >= 1, 而后 内部将计数减1,而后该函数执行完返回 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //二、执行到此处时, semaphore计数为0,表明没有线程修改array [array addObject:[NSNumber numberWithInteger:i]]; //三、处理结束,修改信号量semaphore 加1,若是有dispatch_semaphore_wait函数等待,那么最早等待的那个线程就先执行 dispatch_semaphore_signal(semaphore); }); } NSLog(@"完成"); }
dispatch_semaphore_t,是一个持有计数的信号
//建立信号 设置信号量总数 dispatch_semaphore_t semaphore = dispatch_semaphore_create(5); //释放一个信号,semaphore信号计数 +1 dispatch_semaphore_signal(semaphore); //等待信号,当信号计数 >= 1 时就能够继续向下执行,同时 它将计数 进行减1 操做,,不然一直等待 //参数2 为超时时间, //函数返回result: 0 表明success 信号计数 >=1, 非0 表明超时了,信号计数 <1 long result = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
适用于有限资源的访问限制
五、Group
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_t group = dispatch_group_create(); //添加任务到组 dispatch_group_async(group, queue, ^{ NSLog(@"任务1"); }); dispatch_group_async(group, queue, ^{ NSLog(@"任务2"); }); dispatch_group_async(group, queue, ^{ NSLog(@"任务3"); [NSThread sleepForTimeInterval:5]; }); //任务1,2,3都执行完后才执行该任务 dispatch_group_notify(group, queue, ^{ NSLog(@"最后打印"); }); dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC); //wait函数会阻塞当前线程,直到超时或者group提早执行完成,也能够将等待时间设置为DISPATCH_TIME_NOW,当即返回结果,不会阻塞 // result: 0 表明已完成, 非0 未完成,已超时 long result = dispatch_group_wait(group, time); NSLog(@"%ld", result);
六、dispatch_apply
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //按指定次数将block追加到queue //会阻塞当前线程,等待任务完成 dispatch_apply(10, queue, ^(size_t i) { NSLog(@"%zu", i); }); NSLog(@"最后打印");