1.异步执行
dispatch_async(dispatch_get_main_queue(), ^{
//打算执行的任务
});
dispatch_async:表示异步执行 不用等待里面的代码执行结束就可以往下执行
dispatch_get_main_queue():表示获取主线程
2.Dispatch Queue 种类
Serial Dispatch Queue:等待现在执行中处理结束才能执行其他任务 //串行
Concuerrent Dispatch Queue:不等待现在执行中处理结束就可以执行其他任务 //并行
多个线程更新相同资源时导致数据竞争时使用Serial Dispatch Queue 来保证数据安全
dispatch_queue_t myqueue1 = dispatch_queue_create("com.GCD.myqueue1", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(myqueue1, ^{
NSLog(@"执行的任务");
});
3.Main Dispatch Queue /Global Dispatch Queue 系统自带线程
这俩个是系统提供给我们使用的Dispatch Queue,不用我们去特意创建了
Main Dispatch Queue : 主线程 因为主线程只有一个所以是Serial Dispatch Queue 像UI的刷新必须在主线程中进行
Global Dispatch Queue : 是所有程序都能够使用的Concuerrent Dispatch Queue,另外Global Dispatch Queue有四个执行优先级:
高优先级(High Priority)
默认优先级(Default Priority)
低优先级(Low Priority)
后台优先级(Background Priority)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//可并行执行的处理
});
在向Global Dispatch Queue追加处理时,应选择与处理内容对应执行优先级的Global Dispatch Queue
4.dispatch_set_target_queue 改变线程优先级
dispatch_queue_create函数生成的Dispatch Queue不管是Serial Dispatch Queue还是Concuerrent Dispatch Queue,都使用与默认优先级Global Dispatch Queue相同执行优先级的线程,而变更优先级就需要使用到dispatch_set_target_queue
dispatch_queue_t mySerialQueue = dispatch_queue_create("com.gcd.mySerialQueue", NULL);
dispatch_queue_t globalQueueBackground =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(mySerialQueue, globalQueueBackground);
5.dispatch_after 延迟执行
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);
dispatch_after(time, dispatch_ge t_main_queue(), ^{
//延迟3秒执行的任务
});
SEC:表示秒
MSEC:毫秒
ull 是C语言中的数值字面量,是显示表明类型时使用的字符串(表示"unsigned long long")
6.Dispatch 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, ^{
//任务1
});
dispatch_group_async(group, queue, ^{
//任务2
});
dispatch_group_async(group, queue, ^{
//任务3
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//等待上面三个任务全部执行完毕后,执行结束处理
});
7.dispatch_barrier_async 进行数据库操作时避免数据竞争
写入数据不可与读取数据以及其他写入操作并行操作,否则就会发生问题
dispatch_queue_t queue = dispatch_queue_create("com.gcd.ForBarrier", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{ NSLog(@"读取操作"); });
dispatch_async(queue, ^{ NSLog(@"读取操作"); });
dispatch_async(queue, ^{ NSLog(@"读取操作"); });
dispatch_async(queue, ^{ NSLog(@"读取操作"); });
dispatch_barrier_async(queue, ^{ NSLog(@"写入操作"); }); //此时不可以读取数据 可以把其当做一个Serial Dispatch Queue
dispatch_async(queue, ^{ NSLog(@"读取操作"); });
dispatch_async(queue, ^{ NSLog(@"读取操作"); });
dispatch_async(queue, ^{ NSLog(@"读取操作"); });
dispatch_async(queue, ^{ NSLog(@"读取操作"); });
8.dispatch_sync 同步
既然有async 那么就有sync
使用场景:在主线程中使用其他线程进行处理,处理结束后需要立即使用所得到的结果
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_sync(queue, ^{
//处理任务
});
正因为其使用简单,所以也容易引起问题,死锁
如果在主线程执行以下代码就会死锁
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
//执行任务
});
该代码在主线程中执行指定block,并等待其执行结束,而其实在主线程中正在执行这些代码,所以无法追加到主线程的block
9.dispatch_apply
按指定的次数将指定的block追加到指定的线程中,并等待全部处理执行结束
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t index) {
NSLog(@"%zu",index);
});
NSLog(@"Done");
执行结果:
6
4
3
7
5
2
1
9
0
8
Done //Done肯定在最后 因为要等待执行结束
推荐在dispatch_async中非同步执行dispatch_apply 函数
10.dispatch_suspend / dispatch_resume 挂起/恢复
dispatch_suspend(queue);
dispatch_resume(queue);
这些函数对已经执行的处理没有影响,挂起后,追加到线程中但尚未执行的处理在此之后停止执行,而恢复则使得这些处理能够继续执行
11.dispatch_once 应用程序运行期间只执行一次
static dispatch_once_t pred;
dispatch_once(&pred, ^{
//进行初始化
});
该代码即使在多线程环境中执行,也可保证百分百安全
12.Dispatch I/O
在读取较大文件时,如果将文件分成合适的大小并使用Global Dispatch Queue 并列读取的话,速度会快上许多。