简介
对于许多面试题 会经常问一些比较简单问题 问线程 进程区别 或者线程与队列的到底有什么关系. 线程 和进程关系这里就不讲了比较简单
线程与队列的关系和区分
如图 一个程序只有一个主队列, 并且主队列是一个特殊的串行队列
所以说主队列是一个串行队列
绿图(饭堂模型) 并行队列 就是多条线程一起 执行任务没有顺序
如果把这个图看成一个进程的话 那么这个进程里一共开了四条线程.(一个主线程 三个子线程).
如何开线程
在ios里面一共有三种方式 开辟线程 1.NSThread 2.GCD 3.NSOPeration
第一种很少人会用 他是oc开线程的方法 因为有许多缺点 所以很少人会用(缺点:手动管理线程, 无法利用多核技术)
第二种 第三种 需要掌握 这里我们主要说说GCD 是如何开线程的
第三种NSOPeration 是对苹果公司 对GCD 的一个封装(掌握)
GCD 应用广泛
自动开线程 ,延迟操作,运用于单例的创建等.
GCD开线程
大家都听过异步 和同步吧 其实异步和同步 就是用GCD 来写的
大家记住一件事
dispatch_async(dispatch_get_main_queue(), ^{ });异步里参数除非是dispatch_get_main_queue() 这个主队列 其余的包括 全局队列(并行队列) 和串行队列放入这个异步 作为参数时 他们都会自动创建线程
那么在异步添加到 并行队列(全局队列)与串行队列 都会自动开线程那么他们有什么区别吗?
全局队列是什么 他是一个系统自带的并行队列 所以大家以后不用创建并行队列 直接用.
串行队列 需要手动创建 程序里 已经有了一个特殊的串行队列dispatch_get_main_queue()(主队列)主队列比较特殊 异步加入主线程 这个异步不会开启线程 . 会在主线程执行
但是自定义创建的串行队列 就不一样了
/**
* async -- 并发队列(最常用)
* 会不会创建线程:会,一般同时开多条
* 任务的执行方式:并发执行
*/
- (void)asyncGlobalQueue
{
// 获得全局的并发队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 将 任务 添加 全局队列 中去 异步 执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
});
}
/**
* async -- 串行队列(有时候用)
* 会不会创建线程:会,一般只开1条线程
* 任务的执行方式:串行执行(一个任务执行完毕后再执行下一个任务)
*/
- (void)asyncSerialQueue
{
// 1.创建一个串行队列
dispatch_queue_t queue = dispatch_queue_create("cn.heima.queue", NULL);
// 2.将任务添加到串行队列中 异步 执行
dispatch_async(queue, ^{
NSLog(@"-----下载图片1---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片2---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片3---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片4---%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"-----下载图片5---%@", [NSThread currentThread]);
});
把这几行代码粘到你工程中 你就明白了(打印当前线程) 如代码注释所示 异步加入串行队列 无论你写多少异步 加入者个串行队列 他只会开一条线程.
而异步加入全局队列 你有几个异步那么他开几个线程(最好不要超过5个).
线程的锁死
简单的锁死 有些人 会在主线程中 执行dispatch_sync(dispatch_get_main_queue(), ^{ });
这一行的代码 这样会造成锁死
原因
写了这句话他会加入主线程队列里 等待主线程完成 才回返回block里面的内容.但是当程序运行到这行代码 由于主线程没有完成 block 不会有返回.并且也不会跳过这行代码 所以就造成了死锁现象.
主队列和主线程的区别
代码描述[NSOperationQueue mainQueue]主队列 [NSThread mainThread]主线程
二者关系 主队列里 必须有一个主线程 主队列里可以在加线程
同步加入全局队列要注意的是
dispatch_sync 在全局队列是可以写的 等主队列执行完了 它再执行就是了 没什么大不了