您的位置:首页 > 运维架构

【学习总结】【多线程】 多线程概要 & GDC & NSOperation

2015-10-21 20:42 316 查看
基本需要知道的 :

进程 : 简单点来说就是,操作系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在受保护的内存空间内

线程 : 一个进程(进程)想执行任务,必须有线程(所以,每个进程至少有1条线程),线程是进程的基本执行单元.

疑问 : 在一条线程中怎样执行任务? 线程的串行

线程的串行 : 一个线程中任务的执行是串行的(同一时间内,1个线程只能执行一个任务,)

疑问 : 哪有耗时操作怎么办?或者需要同时执行几个任务? 多线程

多线程 : 顾名思义,就是在一个进程中,开启多条线程并行执行任务(同时执行任务) -->实质上原理是,CPU飞速在多条线程中之间调度(切换),看起来一起操作

疑问 : 如果线程非常多,会发生什么情况? 1. CPU调度频率高,消耗大量资源 2.每条线程被调度执行次数降低(效率低)

疑问 : 多线程技术的优缺点 ? 优点 : 1. 适当提高程序执行效率, 2.适当提高系统资源利用率 缺点 : 1. 开启太多,会降低程序性能 2. 开启太多,CPU开销大 3.程序设计非常复杂(线程间的通讯,线程的数据共享)

IOS主线程 : (又称UI线程) 主要作用 :1.显示\刷新UI界面 2.处理UI事件(点击事件,滚动事件,拖拽事件)

疑问 : 多线程技术怎么实现? 方案有哪些? 1.NSThread , 2.GCD , 3.NSOperation

NSThread : OC - 程序员管理(手动创建,销毁) - 面向对象

GCD : C - 自动管理(自动创建,销毁) - 面向对象 - 充分利用设备的多核 - 自动管理多线程

NSOperation : OC - 自动管理(自动创建,销毁) - GCD的高级封装

疑问 : 多线程技术的隐患? 1. 多个线程可能会访问同一块资源,容易引发数据错乱和数据安全 - 安全隐患解决(互斥锁)

疑问 : 什么是线程同步? 为什么需要线程同步? 1.线程同步就是多条线程在同一条线上执行 2.有时候避免多条线程访问同一份资源,就需要加锁,加锁的操作就等于将所有线程访问这个资源应该按顺序来执行.(主要是避免引发数据错乱和数据安全)

/*
GCD (Grand Central Dispatch)的两个核心概念
任务 : 执行什么操作
* 用Block来封装任务

队列 : 用来存放任务
* 全局的并发队列  :  可以让任务并发执行

所以 : GCD的使用也就两步

1 -> 确定想做的事情(确定任务)

2 -> GCD会自动将队列中得任务取出, 放到对应的线程中执行
任务的取出遵循队列的FIFO原则: 先进先出 , 后进后出

-------------------------------------队列的创建方式-------------------------------------------------

// 两个参数, 前面的参数一般用default ,后面参数默认0,暂时没用
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

* 自己创建的串行队列 : 让任务一个接着一个执行
// 创建队列名称 , dispatch_queue_t类    注意:cn.cwlng.queue 可以任意写.
dispatch_queue_t queue = dispatch_queue_create("cn.cwlng.queue", NULL);

* 主队列 : 让任务在主线程执行
// 获取主队列
dispatch_queue_t queue = dispatch_get_main_queue();

------------------------------------执行任务的函数-------------------------------------------------

* 同步执行 : 不具备开启新线程的能力
dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)

* 异步执行 : 具备开启新线程的能力
dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)

------------------------------------常见的组合与它们之间的通讯---------------------------------------

*  dispatch_async  + 全局并发队列 ;

*  dispatch_async  + 自己创建的串行队列;

*  线程间的通讯

dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行耗时的异步操作...
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,执行UI刷新操作
});

});

------------------------------------  延迟执行  -------------------------------------------------

* 一旦定制好延迟任务后, 不会卡住当前线程  performSelector
//afterDelay秒后,执行SEL方法,并传入WithObject参数
[self performSelector:<#(SEL)#> withObject:<#(id)#> afterDelay:<#(NSTimeInterval)#>]

* 利用GCD函数执行延迟执行操作  dispatch_after
// 获取默认并发线程 , 注意: 这里获取是并发线程的话,下面就在子线程中执行,如果是主线程,则时间过后,跳回主线程执行操作
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 延迟加载
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), queue, ^{
NSLog(@"这里是执行代码的操作");

});

------------------------------------  一次性代码  -------------------------------------------------
// 一次性代码
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 这里的代码,在程序运行过程中,永远只会执行一次

});

*/

/* 串行队列

创建方式 :
1 -> 使用 dispatch_queue_create函数创建串行队列

// 创建队列名称 , dispatch_queue_t类    注意:cn.cwlng.queue 可以任意写.
dispatch_queue_t queue = dispatch_queue_create("cn.cwlng.queue", NULL);

2 -> 使用主队列(根主线程相关联的队列)

主队列是GCD自带的一种特殊的串行队列
放在主队列中得任务,都会放到主线程中执行

// 获取主队列
dispatch_queue_t queue = dispatch_get_main_queue();

*/

/*  释放内存结论
1. 凡是函数名中带有 create \ copy \ new \ retain 等字眼,都应该在不需要使用这个数据的时候进行release
2. GCD的数据类型在ARC环境下不需要再作release
3. CF(Code Foundation)的数据类型在ARC\MRC环境下都需要在做release

*/


GCD 基本操作

四个术语 : 同步, 异步, 并发 , 串行

同步&异步主要影响能不能开启新的线程

* 同步执行 : 在当前线程中执行任务, 不具备开启新线程的能力

dispatch_sync(<#dispatch_queue_t queue#>, <#^(void)block#>)

* 异步执行 : 在新的线程中执行任务 , 具备开启新线程的能力

dispatch_async(<#dispatch_queue_t queue#>, <#^(void)block#>)

并发&串行主要影响 : 任务的执行方式

* 并发队列 : 可以让多个任务并发(同时)执行 (其实就是自动开启多个线程同时执行任务)

* 串行队列 : 让任务一个接着一个地执行 (一个任务执行完后,再执行下一个任务)

问问自己:

什么是GDC?

GDC是(Grand Central Dispatch) 其实就是帮助管理多线程的一套API.

既然是一套API,那么GDC怎么管理多线程?

GDC 有两个核心的概念,任务和队列

任务 : 执行怎样的操作.

队列 : 用来存放任务.

-> 所以 利用GDC管理就是,确定想做的事情(确定任务),然后将任务放到队列中,GDC会自动将队列的任务中拿出来执行

GDC从队列中取出任务,是遵循,先进先出的原则的.

那GDC队列的创建方式有哪一些呢?

-> 首先要知道,队列是分两种形式, 并行队列和串行队列.

并行队列 : 任务在并行队列中会同时执行.

串行队列 : 任务在串行任务中会一个任务一个任务地执行.

-> 需要掌握的三种创建队列的方法(这里总结一下,具体方式请看上面代码块)

* 创建并行队列.一般使用Default模式

* 创建自定义的串行队列.

* 创建系统的主队列.

任务添加进去队列后,队列有什么方式去执行任务呢?

* 同步执行 : 不具备开启新线程的能力

dispatch_sync

* 异步执行 : 具备开启新线程的能力

dispatch_async

执行的过程中,很多时候需要线程之间的通讯,怎么实现线程中得通讯呢?

GDC的方法调用非常方便 , 只需要在线程执行的过程中,也就是那个Block代码块里面

添加你需要通讯的那个线程即可,然后GDC会自动调用Block代码块,实现互相通讯

--------------------------------------------------NSOperation多线程--------------------------------------------------------------------------

/*
NSOperation & NSOperationQueue
1. 队列的类型

->  主队列(同步串行执行)
* [NSOperation mainQueue]
* 添加到"主队列"中的操作,都会放到主线程中执行

->  非主队列(默认创建即是异步并发执行)
* [[NSOperation alloc] init]
* 添加到"非主队列"中的操作,都会放到子线程中执行

2. 将任务添加到队列中
-> - (void)addOperation:(NSOperation *)op;
-> - (void)addOperationWithBlock(void (^)(void))block;

3. 队列的常见用法

-> 设置最大并发数
* get方法 - (NSInteger)maxConcurrentOperationCount;
* set方法 - (void)setMaxConcurrentOperationCount:(NSInteger)cnt

->队列其他操作

* 取消所有的操作
[queue cancelAllOperations]; // 取消队列中的所有任务(不可恢复)

* 暂停所有操作
[queue setSuspended:YES]; // 暂停队列中的所有任务

* 恢复所有操作
[queue setSuspended:NO]; // 恢复队列中的所有任务

4. 操作之间的依赖
// 设置依赖
// B依赖A , C依赖B
// 就是等操作A执行完毕后,才能执行B, B执行完后,才能执行C
[operationB addDependency:operationA];
[operationC addDependency:operationB];

注:   * 不能相互依赖
* 可以在不同的QUEUE的NSOperation之间创建依赖关系

5. 线程之间的通讯

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
// 1.执行耗时操作

// 2.回到主线程
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// 在这里执行在主线程的UI界面刷新操作
}];
}];

6. 从其他线程回到主线程的方式
->perform
*  performSelectorOnMainThread

->GCD
*  dispatch_async(dispatch_get_main_queue(), ^{

});

->NSOperationQueue
*  [[NSOperationQueue mainQueue] addOperationWithBlock:^{

}];

*/


NSOperation&NSOperationQueue是什么?

以GDC为底层,比GDC多了一些更简单实用的功能,并且更加面向对象的一套线程技术

怎么操作NSOperation?

和GDC一样, 也有队列和任务(操作)两个概念

通过操纵NSOperationQueue(队列),并且修改队列的某些属性,从而控制整个线程管理

创建队列的方式有两种 一是主队列,也就是主线程队列(同步串行队列) ,二是非主队列(默认异步并发队列)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: