GCD实现多线程的方式:不需要程序员去创建和管理线程,只需创建一个调度队列Dispatch Queue,将Block事件添加到这个队列即可。
一种内核级实现并发编程方式,能够高效地“窃取”多核CPU性能。
Dispatch Queue
dispatch_time_t getData(NSDate *date){
NSTimeInterval interval;
double second, subsecond;
struct timespec time;
dispatch_time_t miletone;
interval = [date timeIntervalSince1970];
subsecond = modf(interval, &second);
time.tv_sec = second;
time.tv_nsec = subsecond * NSEC_PER_SEC;
miletone = dispatch_walltime(&time, 0);
return miletone;
}
//创建队列
//串行队列 第一个参数,指定串行队列的名称,第二个参数为NULL的话就是串行的
dispatch_queue_t seriQueue = dispatch_queue_create("com.test", NULL);
dispatch_async(seriQueue, ^{
});
//并行队列 第一个参数还是队列名称 第二参数为并行
dispatch_queue_t conQueue = dispatch_queue_create("com.con", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(conQueue, ^{
});
//获取系统提供的队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_queue_t lowQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_queue_t highQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t backQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
//访问和读取数据库操作
//注意:这里的并行队列只能使用自定义的并行队列才能达到如下需求
//1、2、3、4无序输出 接着输出5 然后6、7、8、9无序输出
dispatch_async(conQueue, ^{
NSLog(@"=1");
});
dispatch_async(conQueue, ^{
NSLog(@"=2");
});
dispatch_async(conQueue, ^{
NSLog(@"=3");
});
dispatch_async(conQueue, ^{
NSLog(@"=4");
});
dispatch_barrier_async(conQueue, ^{
NSLog(@"=5");
});
dispatch_async(conQueue, ^{
NSLog(@"=6");
});
dispatch_async(conQueue, ^{
NSLog(@"=7");
});
dispatch_async(conQueue, ^{
NSLog(@"=8");
});
dispatch_async(conQueue, ^{
NSLog(@"=9");
});
//seriQueue 要变更的队列
//mainQueue 按这个队列的优先级执行
dispatch_set_target_queue(seriQueue, mainQueue);
//延迟做某事
//第一种方式 60s 后
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(60 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
});
//第二种方式 60ms 后
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 60ull * NSEC_PER_MSEC);
dispatch_after(time, mainQueue, ^{
});
//传入一个日期,定时这个日期下操作某事(闹钟功能)
dispatch_after(getData([NSDate new]), mainQueue, ^{
});
//创建队列组
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, defaultQueue, ^{
});
dispatch_group_async(group, defaultQueue, ^{
});
dispatch_group_async(group, defaultQueue, ^{
});
dispatch_group_notify(group, defaultQueue, ^{
});
long result = dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
if (result == 0) {
//所有的线程执行完毕
} else {
//仍有线程在运行。
}
long result1 = dispatch_group_wait(group, DISPATCH_TIME_NOW);
dispatch_async(defaultQueue, ^{
//可作为数组的循环
dispatch_apply(10, highQueue, ^(size_t index) {
NSLog(@"%zu", index);
if (index == 5) {
//暂停队列
dispatch_suspend(highQueue);
}
});
NSLog(@"结束");
//恢复队列
dispatch_resume(highQueue);
});
//信号量创建 dispatch semaphore 是持有计数的信号,该计数是多线程编程中的计数类型信号。所谓信号,类似于过马路时常用的手旗。可以通过时举起手旗,不可通过时放下手旗。而在dispatch semaphore中,使用计数来实现该功能。计数为0时等待,计数为1或大于1时,减去1而不等待
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_semaphore_signal(semaphore); //让信号量加1
long esult = dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); //如果信号量大于或等于1,不等待且减1
if (esult == 0) {
NSLog(@"完成");
}
NSMutableArray *array = [NSMutableArray array];
dispatch_semaphore_t sem = dispatch_semaphore_create(1); //信号量等于1
dispatch_async(defaultQueue, ^{
dispatch_apply(10, defaultQueue, ^(size_t index1) {
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); //信号量减1
NSLog(@"====%zu", index1);
[array addObject:@"1"];
dispatch_semaphore_signal(sem); //信号量加1
});
dispatch_async(mainQueue, ^{
NSLog(@"====%lu", (unsigned long)array.count);
});
});
Dispatch Source
它是BSD系内核惯有功能kqueue的包装。其CPU负荷非常小,尽量不占用资源。
//dispatch source 可处理以下事件:
DISPATCH_SOURCE_TYPE_TIMER; //定时器
DISPATCH_SOURCE_TYPE_WRITE; //可读取文件映像
DISPATCH_SOURCE_TYPE_DATA_ADD; //变量增加
DISPATCH_SOURCE_TYPE_DATA_OR; //变量OR
DISPATCH_SOURCE_TYPE_MACH_SEND; //MACH 端口发送
DISPATCH_SOURCE_TYPE_MACH_RECV; //MACH 端口接收
DISPATCH_SOURCE_TYPE_PROC; //检测到与进程相关的事件
DISPATCH_SOURCE_TYPE_SIGNAL; //接收信号
DISPATCH_SOURCE_TYPE_VNODE; //文件系统有变更
DISPATCH_SOURCE_TYPE_WRITE; //可写入文件映像
//在定时器经过指定时间时设置main queue 为追加处理的dispatch Queue
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
/**
将定时器设定为15秒后 (立即执行:设置为 dispatch_walltime(NULL, 0))
不指定重复(每秒重复做某事可设置为 1.0*NSEC_PER_SEC )
允许迟延1秒
*/
dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, 15 * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 1*NSEC_PER_SEC);
//指定定时器指定时间内执行的处理
dispatch_source_set_event_handler(timer, ^{
NSLog(@"执行这句代码");
//取消dispatch source
dispatch_source_cancel(timer);
});
dispatch_source_set_cancel_handler(timer, ^{
NSLog(@"取消处理");
});