###一、iOS多线程 ######iOS多线程开发有三种方式:

  1. NSThread
  1. NSOperation
  2. GCD

iOS在每个进程启动后都会创建一个主线程更新UI要在主线程上,所以也称为UI线程,是其他线程的父线程。

######线程和进程的区别傻傻分不清楚:

  • 线程(thread):用于指代独立执行的代码段。
  • 进程(process):用于指代一个正在运行的可执行程序,它可以包含多个线程。

###二、NSThread NSThreadhi轻量级的多线程开发,需要自己管理线程生命周期 ######创建线程主要实现方法:

/* 直接将操作添加到新线程中并执行,该方法无法拿到线程对象 */
+ (void)detachNewThreadSelector:(SEL)selector /* 方法名 */toTarget:(id)target /* 调用对象 */withObject:(id)argument; /* 参数 */
/* 创建线程对象,初始化线程任务,调用start方法启动线程 */
- (instancetype)initWithTarget:(id)target /* 调用对象 */selector:(SEL)selector /* 方法名 */object:(id)argument;/* 参数 */
复制代码

######实际使用:

/* 创建一个线程,初始化任务,创建线程并不会启动线程 */
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(loadImage) object:nil];
[thread start];//启动线程/* 直接将操作添加到新线程并启动线程 */
[NSThread detachNewThreadSelector:@selector(loadImage) toTarget:self withObject:nil];
复制代码
  • 每个线程的实际执行顺序并不一定按启动顺序执行
  • 如果是单核CPU,多线程是并发,分时间片切换执行不同线程,多核CPU的多线程才是真正的并行运算。

######线程状态分为:

  • isExecuting(正在执行)
  • isFinished(已经完成)
  • isCancellled(已经取消)

######下面是常用方法来控制线程:

/* 让线程休眠 */
+ (void)sleepUntilDate:(NSDate *)date;/* 让当前执行线程休眠到某个时间 */
+ (void)sleepForTimeInterval:(NSTimeInterval)time;/* 让当前执行线程休眠固定多少秒 */
/* 终止线程 */
+ (void)exit;
/* 停止线程,注意在主线程中调用仅仅只是设置线程状态,不会立刻停止线程 */
- (void)cancel;
复制代码

######实例:

NSThread *thread = threads[i];
//判断线程是否完成,如果没有完成则设置为取消状态
//注意设置为取消状态仅仅是改变了线程状态而言,并不能立刻终止线程
if ( !thread.isFinished ) {[thread cancel];
}
//线程休眠2秒
[NSThread sleepForTimeInterval:2.0];
复制代码

我们知道了控制单个线程,怎么在线程之间进行通信呢? ######下面是线程间通信的常用方法:

/* 在后台执行一个操作,本质就是重新创建一个线程执行当前方法 */
- (void)performSelectorInBackground:(SEL)aSelectorwithObject:(id)arg;
/* 在指定的线程上执行一个方法,需要用户创建一个线程对象 */
- (void)performSelector:(SEL)aSelectoronThread:(NSThread *)thrwithObject:(id)argwaitUntilDone:(BOOL)wait;
/* 在主线程上执行一个方法 */
- (void)performSelectorOnMainThread:(SEL)aSelectorwithObject:(id)argwaitUntilDone:(BOOL)wait;
复制代码

###三、NSOperation 只要将NSOperation放入NSOperationQueue线程队列中,就会启动执行。 NSOperationQueue负责管理、执行所有的NSOperation,这样更加容易管理线程总数控制线程之间的依赖。 ######NSOperation是个基类,我们直接使用的是它的子类:

  • NSInvocationOperation:调用方法SEL的方式执行线程可以使用它
  • NSBlockOperation:调用Block的方式执行线程可以使用它

######下面是使用实例:

//创建Invocation线程
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(loadImage) object:nil];
//注意如果直接调用start方法,则此操作会在主线程中调用
// [invocationOperation start];//一般不会这么操作,而是添加到NSOperationQueue中
//创建线程队列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
operationQueue.maxConcurrentOperationCount = 5;//设置最大并发线程数
//注意添加到线程队列后,队列里的线程就会开始执行
[operationQueue addOperation:invocationOperation];//创建Block线程
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{[self loadImage:[NSNumber numberWithInt:0]];
}];
//添加进线程队列
[operationQueue addOperation:blockOperation];
复制代码

如果觉得添加NSBlockOperation线程麻烦,还有个简单的方法,是NSOperationQueue的对象方法:

// 快捷添加NSBlockOperation
[operationQueue addOperationWithBlock:^{[self loadImage:[NSNumber numberWithInt:0]];
}];
复制代码

我说过NSOperationQueue可以控制线程之间的依赖,这是怎么一回事呢?想象一种场景,加载多个图片,但我想最后一张图片一定要先加载,其他图片加载的前提就是最后一张图片要加载完成,这时候就可以使用依赖了。非常简单。 ######多图片加载实例:

- (void)loadImageWithMultiThread{int count = ROW_COUNT*COLUMN_COUNT;//创建线程队列NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];operationQueue.maxConcurrentOperationCount = 5;//设置最大并发线程数//创建加载最后一张图片的线程NSBlockOperation *lastBlockOperation = [NSBlockOperation blockOperationWithBlock:^{[self loadImage:[NSNumber numberWithInt:(count-1)]];}];//创建多个线程用于下载其他图片for (int i=0; i<count-1; ++i) {//创建多线程操作NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{[self loadImage:[NSNumber numberWithInt:i]];}];//设置依赖操作为最后一张图片加载操作,只有最后一张图片加载完成,其他图片才开始陆续加载[blockOperation addDependency:lastBlockOperation];[operationQueue addOperation:blockOperation];}//将最后一个图片的加载线程加入线程队列[operationQueue addOperation:lastBlockOperation];
}
复制代码

###四、GCD GCD中也有一个类似于NSOperationQueue的队列,GCD统一管理整个队列中的任务,GCD是C语言下的框架。 ######GCD中的队列分为并行队列和串行队列:

  • 串行队列(serial):只有一个线程,加入到队列中的操作按添加顺序依次执行。
  • 并发队列(concurrent):有多个线程,操作进来之后它会将这些队列安排在可用的处理器上,同时保证先进来的任务优先处理,但不是顺序的。

其实在GCD中还有一个特殊队列就是主队列,用来执行主线程上的操作任务。

######GCD执行方式也分为异步执行和同步执行:

  • dispatch_async(异步执行) :不管队列中的任务执行完还是没执行完,直接将任务追加到队列
  • dispatch_sync(同步执行) : 等队列中的任务执行完,再将任务追加到队列

######串行队列和并发队列的创建:

/*创建一个队列第一个参数:队列名称第二个参数:队列类型,DISPATCH_QUEUE_SERIAL串行,DISPATCH_QUEUE_CONCURRENT并发注意:GCD的queue不是指针类型
*/
dispatch_queue_t serialQueue = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t concurrentQueue = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);/* 使用dispatch_get_global_queue() 方法取得一个全局的并发队列 */
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);复制代码

######队列的异步执行和同步执行:

//异步执行队列任务,第一个参数是队列,第二个参数是任务Block
dispatch_async(queue, ^{[self loadImage:[NSNumber numberWithInt:i]];
});
//同步执行队列任务,第一个参数是队列,第二个参数是任务Block
dispatch_sync(queue, ^{[self loadImage:[NSNumber numberWithInt:i]];
});
复制代码
  • 在GDC中一个操作是多线程执行还是单线程执行,取决于当前队列类型和执行方法,只有队列类型为并行队列并且使用异步方法执行时才能在多个线程中并发执行
  • 串行队列可以按顺序执行,并行队列的异步方法无法确定执行顺序。
  • 更新UI界面最好采用同步方法,其他操作采用异步方法。

######GCD的其他任务执行方法:

/* 重复执行某个任务,为了不阻塞线程可以使用dispatch_async()包装一下再执行 */
dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t));/* 单次执行一个任务,此方法中的任务只会执行一次,重复调用也没办法重复执行(单例模式中常用此方法)*/
dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);/* 常用:延迟delayInSeconds秒后在队列queue执行block操作 */
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_queue_t queue, dispatch_block_t block);
复制代码

###五、线程同步 为什么需要线程同步?因为要解决多线程的资源抢夺的问题 ####1.NSLock同步锁

//初始化锁对象
NSLock *myLock = [[NSLock alloc] init];
//加锁
[myLock lock];//加锁后,下面的代码只能有一个线程进入执行
if (_imageNames.count > 0) {name = [_imageNames lastObject];[_imageNames removeObject:name];
}
//使用完解锁
[myLock unlock];
复制代码

####2.@synchronized代码块

//线程同步
@synchronized(self){if (_imageNames.count > 0) {name = [_imageNames lastObject];[_imageNames removeObject:name];}
}
复制代码

线程同步就不细讲了,这是一个大块知识。 #####如果你喜欢我的文章,请关注我O(∩_∩)O哈~

转载于:https://juejin.im/post/5b126db2e51d4506d0620870

iOS学习笔记11 多线程入门相关推荐

  1. iOS学习笔记-地图MapKit入门

    代码地址如下: http://www.demodashi.com/demo/11682.html 这篇文章还是翻译自raywenderlich,用Objective-C改写了代码.没有逐字翻译,如有错 ...

  2. iOS学习笔记11-多线程入门

    一.iOS多线程 iOS多线程开发有三种方式: NSThread NSOperation GCD iOS在每个进程启动后都会创建一个主线程,更新UI要在主线程上,所以也称为UI线程,是其他线程的父线程 ...

  3. iOS学习笔记-105.多线程04——CGD基础

    多线程04CGD基础 一CGD简介 1 什么是GCD 2 GCD的优势 二任务和队列 1 GCD中有2个核心概念 2 GCD的使用就2个步骤 三执行任务 1 执行任务的方法 2 同步和异步的区别 3 ...

  4. iOS学习笔记-109.多线程08——CGD快速迭代

    多线程08CGD快速迭代 一说明 二for迭代 三GCD的快速迭代 四使用for迭代移动文件示例 1 说明 2 示例代码 3 图示与结果 五使用for迭代移动文件示例 1 示例代码 2 图示与结果 多 ...

  5. iOS学习笔记-110.多线程09——CGD队列组

    多线程09CGD队列组 一需求说明 二通知使用 dispatch_group_notify 1 队列组的使用可以分为四个步骤 2 示例代码 2 结果 三通知使用 dispatch_group_wait ...

  6. iOS学习笔记-108.多线程07——CGD栅栏函数、延时、一次性代码

    多线程07CGD栅栏函数延时一次性代码 一说明 1 栅栏函数说明 2 延时执行 3 一次性代码 二栅栏函数 1 说明 2 代码 3 结果 4 结果分析 三延时执行 1 调用NSObject的方法 2 ...

  7. iOS学习笔记-106.多线程05——CGD同步、异步函数和并行、串行、主队列示例

    多线程05CGD同步异步函数和并行串行主队列示例 一说明与图示 二异步函数 并发队列 1 代码 2 结果 三异步函数 串行队列 1 代码示例 2 结果 四同步函数 并发队列 1 代码示例 2 结果 五 ...

  8. 逐梦旅程学习笔记 DirectX开发入门02:旋转的彩色立方体

    本文是 系列笔记DirectX部分的第2篇,上一篇参见 逐梦旅程学习笔记 DirectX开发入门01:应用程序基本框架 这个示例增加了一些实际的内容,首先是绘制一个颜色随机变幻的彩色立方体,其二是显示 ...

  9. 点云学习笔记11——VoxelNet算法+代码运行

    点云学习笔记11--VoxelNet算法+代码运行 一.算法分析 摘要 介绍 相关工作 1.2. 贡献 2.VoxelNet 2.1.特征学习网络 2.1.1 特征学习网络 二.代码复现 2.1.环境 ...

最新文章

  1. imagenet 测试精度记录
  2. 阻塞与非阻塞个人小结
  3. nth-of-type(n)
  4. ssh excel 导入 mysql_ssh poi解析excel并将数据存入数据库
  5. 在XX公司工作第二天,维护已有代码
  6. spring mvc学习(37):JavaEE-JSP基础-EL表达式和JSTL标签库(Taglibs)
  7. IDEA 启动、编译、clean、安装maven等、报错Process terminated
  8. linux下c 指针变量大小,C语言sizeof关键字
  9. redhat,centos Linux常用命令LS之常用功能
  10. Oracle数据库——触发器的创建与应用
  11. 共享usb接口给虚拟机_多网卡虚拟机如何设置?收藏绝对有用
  12. 关于打开NVIDIA控制面板闪退问题
  13. 用Node.JS分析steam所有的游戏!
  14. 俄内政部悬赏破解 Tor 匿名网络
  15. 图片实现裁剪功能vue-img-cutter
  16. Chrome 安装插件 win10 Edge 安装 位置
  17. 【游戏逆向】游戏玩家技能冷却分析
  18. vasp能装在window系统里吗_Window安装系统详解
  19. Robocup 2D 的学习
  20. Android Hawk数据库的源码解析,Github开源项目,基于SharedPreferences的的存储框架

热门文章

  1. Java 数据库连接池的技术选型都应考虑哪些要素
  2. 如何帮孩子成为最好的自己
  3. js初级——复习html+css
  4. Transposed Convolution 反卷积
  5. C++程序设计:原理与实践(进阶篇)15.4 链表
  6. suse配置dhcp服务器
  7. 批处理延迟sleep应用
  8. Linux查看负载相关命令
  9. 链接选项 rpath 的原理和应用
  10. 360云计算|2019年度精选文章