GCD
进程
进程是一个具有一定独立功能的程序关于某次数据集合的一次运行活动,它是操作系统分配资源的基本单元.在移动端一个运行的app就是一个进程
线程
1.程序执行流的最小单元,线程是进程中的一个实体.
2.一个进程要想执行任务,必须至少有一条线程.应用程序启动的时候,系统会默认开启一条线程,也就是主线程
进程和线程的关系
1.线程是进程的执行单元,进程的所有任务都在线程中执行
2.线程是 CPU 分配资源和调度的最小单位
3.一个程序可以对应多个进程(多进程),一个进程中可有多个线程,但至少要有一条线程
4.同一个进程内的线程共享进程资源
多线程
多线程的实现原理:
单核的CPU 同一时间内只能执行一个线程,多线程是CPU快速的在多个线程之间进行切换(调度),造成了多个线程同时执行的假象。
多核CPU就是不同CPU执行不同的线程,实现物理上的同时出来多个线程了。
多线程的目的是为了同步完成多项任务,通过提高系统的资源利用率来提高系统的效率。
在iOS中将一些比较耗时的操作放在另一条执行路径中,让他与主线程同时运行,这样不会造成主线程的阻塞
死锁:两个人都要用一个东西造成争执不下
GCD
将block块中的任务放到队列中去执行,由队列负责任务执行所在的线程及执行时间。
队列:这里的队列指执行任务的等待队列,即用来存放任务的队列。队列是一种特殊的线性表。队列的特点是先进先出的,新增的到队列的任务会排到队尾。
GCD有两种队列(dispatch_queue_t):串行队列,并行队列。两者的主要区别是:执行顺序不同,以及开启线程数不同
串行队列:每次只有一个任务被执行,让任务一个接一个的执行。(只开启一个线程,一个任务执行完后,执行另一个任务)主队列(dispatch_get_main_queue)是特殊的串行队列
并行队列:可以让多个任务并发(同时)执行。(可以开启多个线程,并同时执行任务)全局队列(dispatch_get_main_queue)是特殊的并行队列
任务:即操作,你想要干什么,说白了就是一段程式码,在GCD中就是一个Block,所以新增任务十分方便。
任务有两种执行方式:同步执行和非同步执行,他们之间的区别主要在于会不会阻塞当前执行绪
同步任务(sync):同步执行的任务叫同步任务
同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再继续执行。
只能在当前线程中执行任务,不具备开启新线程的能力。
异步任务(async):非同步执行的任务叫异步任务
异步添加任务到指定的队列中,它不会做任何等待,可以继续执行任务。
可以在新的线程中执行任务,具备开启新线程的能力。
任务是在单线程下执还是多线程下主要还是看队列的类型和任务执行的方式:
并行队列异步执行才能在多线程;
并行队列同步执行只会在主线程执行;
串行队列异步执行才能在多线程;
串行队列同步执行只会在主线程执行;
主队列异步执行只会在主线程;
主队列同步执行会发生死锁;
//并行队列
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
//异步任务
dispatch_async(queue, ^{
NSLog(@"多线程执行%d",[[NSThread currentThread] isMainThread]);
});
//并行队列
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT);
//同步任务
dispatch_sync(queue, ^{
NSLog(@"在主线程执行%d",[[NSThread currentThread] isMainThread]);
});
//串行队列
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
//异步任务
dispatch_async(queue, ^{
NSLog(@"多线程执行%d",[[NSThread currentThread] isMainThread]);
});
//串行队列
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL);
//同步任务
dispatch_sync(queue, ^{
NSLog(@"在主线程执行%d",[[NSThread currentThread] isMainThread]);
});
//主队列
dispatch_queue_t queue = dispatch_get_main_queue();
//异步任务
dispatch_async(queue, ^{
NSLog(@"在主线程执行%d",[[NSThread currentThread] isMainThread]);
});
//主队列
dispatch_queue_t queue = dispatch_get_main_queue();
//同步任务
dispatch_sync(queue, ^{
NSLog(@"死锁%d",[[NSThread currentThread] isMainThread]);
});
全局队列创建方式
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
全局队列在使用是最好使用默认优先级,因为设置优先级容易造成”优先级反转“。具体的可以自行了解
一个串行队列实例
dispatch_queue_t _serialQueue;//调度队列
//创建串行队列
- (dispatch_queue_t)serialQueue
{
if (!_serialQueue) {
//DISPATCH_QUEUE_SERIAL串行队列 DISPATCH_QUEUE_CONCURRENT 为并行队列(创建并行队列时队列)
_serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
}
return _serialQueue;
}
//添加一个异步请求到该队列中 执行异步请求
dispatch_async([self serialQueue], ^{
[weakSelf requestPersonInfo];//这是第一个任务
/*dispatch_sync([self serialQueue], ^{//执行同步请求
NSLog(@"串行队列开启异步任务后嵌套同步任务造成死锁,串行队列中开启同步任务后嵌套同步任务造成死锁");
});*/
});
//再添加一个异步请求到该队列中
dispatch_async([self serialQueue], ^{
[self requestVedioList];//把block中的任务放入串行队列中执行,这是第二个任务
});
//获取主队列并执行异步操作
//涉及UI更新的操作,放入主线程中.主线程队列中不能开启同步,会阻塞主线程。用dispatch_sync尝试下
dispatch_async(dispatch_get_main_queue(), ^{
_labelTitle.text = infoDB.tilte;
});
一个并行调度组队列实例
//队列调度组
dispatch_group_t _groupQueue;
//创建一个线程队列组.该组内所有线程执行完成后会回调一个方法。通知组内所有线程已经完成
- (dispatch_group_t)groupQueue{
if(!_groupQueue){
_groupQueue = dispatch_group_create();
}
return _groupQueue;
}
dispatch_group_async([self groupQueue], dispatch_get_global_queue(0,0), ^{
dispatch_group_enter([self groupQueue]);
// 并行执行的线程一
dispatch_group_leave([self groupQueue]);
});
dispatch_group_async([self groupQueue], dispatch_get_global_queue(0,0), ^{
dispatch_group_enter([self groupQueue]);
// 并行执行的线程二
dispatch_group_leave([self groupQueue]);
});
dispatch_group_notify([self groupQueue], dispatch_get_global_queue(0,0), ^{
// 汇总结果
});
//通过GCD创建单例
+ (instancetype)lessionInfoViewControllerInfo
{
static LessionInfoViewController *lessionInfoViewController = nil;
static dispatch_once_t onceToken;//仅执行一次
dispatch_once(&onceToken, ^{
lessionInfoViewController = [[LessionInfoViewController alloc] init];
});
return lessionInfoViewController;
}