多线程的优点:
1、能适当提高程序的执行效率。
2、能适当提高资源利用率(CPU、内存利用率)
多线程的缺点:
1、开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能
2、线程越多,CPU在调度线程上的开销就越大
3、程序设计更加复杂:比如线程之间的通信、多线程的数据共享
4、CPU在同一时间只能执行一个线程,之所以看起来多个线程能同时进行工作,这是因为CPU在多个线程之间来回切换的原因,如果cpu来回切换的速度够快,就造成了多线程并发执行的假象。
我们使用的Dispatch Queue有以下几种:
Global Queue-全局并发队列,由整个进程共享。队列中的任务按照FIFO顺序执行,同一时间可同时执行多个任务。
// 第1个参数表示队列执行的优先级:
// DISPATCH_QUEUE_PRIORITY_HIGH-高优先级
// DISPATCH_QUEUE_PRIORITY_DEFAULT-中优先级
// DISPATCH_QUEUE_PRIORITY_LOW-低优先级
// DISPATCH_QUEUE_PRIORITY_BACKGROUND-最低优先级
// 第2个参数暂不支持,传0即可;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
Main Queue-主线程队列,属于串行队列
。队列中的任务按照FIFO顺序在主线程中执行,因为是串行队列,同一时间只能执行一个任务。
dispatch_queue_t queue = dispatch_get_main_queue();
用户队列-用户自定义创建,可并发可串行。同样的队列中的任务按照FIFO顺序执行。
// 第一个参数:
// 队列ID,需要传递一个字符串,命名分格采用类似com.example.myqueue的格式;
// 第二个参数:
// 在ios 4.3以前不支持,传NULL即可;
// 在ios 4.3以后,这个参数表示队列类型。DISPATCH_QUEUE_SERIAL-创建一个串行队列;DISPATCH_QUEUE_CONCURRENT-创建一个并发队列;
dispatch_queue_t queue = dispatch_queue_create("", NULL);
常用的GCD接口有哪些?
1、dispatch_async
作用:提交block至指定的队列中并异步执行,函数在第一时间返回。常见用法如下
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗时的操作
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面
});
});
2、dispatch_group_async(1) / dispatch_group_wait (2)/ dispatch_group_notify(3)
作用:(1)提交block至指定队列中并和一个dispatch_group_t对象关联,函数异步执行将在第一时间返回;
(2)同步等待至指定group中的block执行完毕或执行超时函数才返回;
(3)设置观察某个指定的group,等group中的block全部执行完毕后,向指定的queue提交block并异步执行;
这3个方法常常是搭配使用的,例如dispatch_group_async/dispatch_group_wait搭配
// 创建队列和组
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
// 向队列中添加block并关联组
dispatch_group_async(group, queue, ^{
// 耗时操作1
});
dispatch_group_async(group, queue, ^{
// 耗时操作2
});
// ...
// 同步等待指定group执行完毕或超时
// 超时时间可以设为:DISPATCH_TIME_FOREVER-永远不超时;DISPATCH_TIME_NOW-很短时间内即超时;
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
// 后续操作,如更新界面
// ...
dispatch_group_async/dispatch_group_notify搭配使用
// 创建队列和组
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
// 向队列中添加block并关联组
dispatch_group_async(group, queue, ^{
// 耗时操作1
});
dispatch_group_async(group, queue, ^{
// 耗时操作2
});
// ...
// group中的block全部完成后添加block至queue;group可以不在queue中;
// dispatch_group_notify是异步的;
dispatch_group_notify(group, queue, ^{
// 耗时操作3
});
// 后续操作,如更新界面
// ...
3、dispatch_apply
作用:提交一个block至指定队列并循环调用多次,直到所有的调用都执行完毕函数才返回。使用方法例如:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 此方法会让主线程同步等待至所有循环调用block都执行完毕才返回
// 在这里,queue最好是传递一个并发队列才能发挥这个方法的最大优势
// index表示循环次数
dispatch_apply(5, queue, ^(size_t index) {
});
// 后续操作,如更新界面
// ...
4、dispatch_barrier_async
作用:提交block到指定队列并异步执行,函数将在第一时间返回;如果这个队列是通过dispatch_queue_create方法创建的并发队列,则这个block要等到它队列前面的所有block执行完毕才会执行,排在这个block后面的block也要等到该block执行完毕才能执行;如果这个队列不是上述队列,则dispatch_barrier_async效果等同于dispatch_async。使用形式形如
dispatch_queue_t queue = dispatch_queue_create("com.zwxx.tiancai", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// some code
});
dispatch_barrier_async(queue, ^{
// some code
});
dispatch_async(queue, ^{
// some code
});
5、dispatch_once
作用:在应用程序的整个生命周期内只执行一次指定的block。常用它实现单例模式
+ (MyObject *)sharedMyObject
{
static MyObject *_singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_singleton = [[MyObject alloc] init];
});
return _singleton;
}