美文网首页程序员
关于多线程的理解(不定时更新)

关于多线程的理解(不定时更新)

作者: Mr姜饼 | 来源:发表于2018-11-26 09:22 被阅读0次

下面会以一小个一小个的知识点进行表达(可能想到哪就写到哪)

1.每一个程序都相当于一个进程,每个进程,系统都会为其分配独立的内存空间运行,所以,ios中每一个app应用都相当于一个进程。

2.一个进程中运行的所有任务都是在线程(Thread)中进行的,每个进程至少有一个线程,也就是所谓的主线程,(下图)

进程、线程的关系

3.app一旦开始运行,就会默认开启一条线程、也就是所谓的“主线程”。主线程的任务一般是:刷新UI;处理UI事件(滑动屏幕、点击....)

4.如果主线程中的操作太多,会造成页面的卡顿、发烫等现象,所以我们会把耗时的任务放在子线程中并发执行,待执行完毕再通知主线程做相应的变化

5.线程是程序执行流的最小单元,是进程中的一个实体。有自己的栈和寄存器.


进阶

多线程的优点:

1.因为可以并发  所以提高了程序的执行效率

2.提高资源的利用率

3.耗时多的任务可以放在线程中,这样不会造成程序卡顿

多线程的缺点

1.线程越多,CPU在调度线程上的开销就越大,占用的内存空间越大

2.线程越多,程序设计就越复杂,比如线程之间的通信,多线程的数据共享,这些都需要程序的处理,增加了程序的复杂度。

多线程的种类

1.PThread:(C语言)

2.NSThread

3.GCD

4.NSOpreation


NSThread

三种开启方法:

1.动态开启:手动开启

NSThread*thread1 = [[NSThrea dalloc] initWithTarget:selfselector:@selector(doSomething1:) object:(@"NSThread1")];[thread1 start];

2.静态开启:创建好直接开启

[NSThread detachNewThreadSelector:@selector(doSomething2:) toTarget:selfwithObject:(@"NSTread2")];

3.隐式开启:创建后直接开启

[selfperformSelectorInBackground:@selector(doSomething3:) withObject:(@"NSTread3")];

【NSthread currentThread】:当前线程 【NSthread mainThread】:主线程

线程之间通信

//在指定线程上执行操作

[self performSelector:@selector(run) onThread:thread withObject:nilwaitUntilDone:YES];

//在主线程上执行操作

[self performSelectorOnMainThread:@selector(run) withObject:nilwaitUntilDone:YES];

//在当前线程执行操作

[self performSelector:@selector(run) withObject:nil];

GCD(Grand Central Dispatch)

优点:

1.自动管理线程的生命周期

2.可用于多核运算

串行队列:(主队列、主线程)先进先出   当执行完一个任务时候 再接着往下进行下一个任务

并行队列:

异常一

如上代码:会崩溃  

分析崩溃原因:

所有的程序,默认就一个主队列和一个主线程,因此viewDidLoad函数这段任务就在主队列中同步执行,dispatch_sync...这段代码表示把B处任务加入主队列中,并且同步执行,这就出问题,B处任务要等主队列中同步执行之前的case1这段任务结束后执行,但B处任务在case1这段任务中,case1又要等B处任务执行完才能继续执行。case1任务要等B处完成才能继续,但case1又排在B处前面,这就尴尬了,所以gg了 😂

GCD 重点

只要是串行队列,肯定要等上一个任务执行完成,才能开始下一个任务。但是并行队列当上一个任务开始执行后,下一个任务就可以开始执行。

同步+串行:未开辟新线程,串行执行任务;

同步+并行:未开辟新线程,串行执行任务;

异步+串行:新开辟一条线程,串行执行任务;

异步+并行:开辟多条新线程,并行执行任务;

在主线程中同步使用主队列执行任务,会造成死锁。

GCD延时方法:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

// 2.0秒后异步追加任务代码到主队列,并开始执行

NSLog(@"after---%@",[NSThreadcurrentThread]);// 打印当前线程

});

dispatch_once:生命周期只执行一次

此方法一般多用于创建单例的时候

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

NSLog(@"就一次%@",[NSThreadcurrentThread]);

 });

NSOperation(操作) 和 NSOperationQueue(操作队列)

NSOperation(任务)、NSOperationQueue(队列)是OC对GCD的封装。

NSOperation是一个抽象类;但是想要使用操作的话  可以用“NSInvocationOperation”“NSBlockOperation”

NSInvocationOperation和NSBlockOperation  在没有配合NSOperationQueue使用时  都是在当前线程中执行;

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];

[operation start];

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"%@", [NSThread currentThread]); }]; 

[operation start]; 

NSOperationQueue的使用

添加任务:

1.- (void)addOperation:(NSOperation *)op;//添加操作任务

2.- (void)addOperationWithBlock:(void (^)(void))block;//不需要先创建操作,直接添加block

根据maxConcurrentOperationCount来控制是并发或者串行

maxConcurrentOperationCount = 1:代表串行

maxConcurrentOperationCount默认是-1;当大于1的时候 代表是并发

NSOperation之间的依赖:B以来A的时候  就等A执行完再执行B;注意不能相互依赖  这样会造成死锁


NSOperation 常用属性和方法

取消操作方法

- (void)cancel;实质是标记 isCancelled 状态。

判断操作状态方法

- (BOOL)isFinished;判断操作是否已经结束。

- (BOOL)isCancelled;判断操作是否已经标记为取消。

- (BOOL)isExecuting;判断操作是否正在在运行。

- (BOOL)isReady;判断操作是否处于准备就绪状态,这个值和操作的依赖关系相关。

操作同步

- (void)waitUntilFinished;阻塞当前线程,直到该操作结束。可用于线程执行顺序的同步。

- (void)setCompletionBlock:(void (^)(void))block;completionBlock 会在当前操作执行完毕时执行 completionBlock。

- (void)addDependency:(NSOperation *)op;添加依赖,使当前操作依赖于操作 op 的完成。

- (void)removeDependency:(NSOperation *)op;移除依赖,取消当前操作对操作 op 的依赖。

@property (readonly, copy) NSArray<NSOperation *> *dependencies;在当前操作开始执行之前完成执行的所有操作对象数组。

5.9 NSOperationQueue 常用属性和方法

取消/暂停/恢复操作

- (void)cancelAllOperations;可以取消队列的所有操作。

- (BOOL)isSuspended;判断队列是否处于暂停状态。 YES 为暂停状态,NO 为恢复状态。

- (void)setSuspended:(BOOL)b;可设置操作的暂停和恢复,YES 代表暂停队列,NO 代表恢复队列。

操作同步

- (void)waitUntilAllOperationsAreFinished;阻塞当前线程,直到队列中的操作全部执行完毕。

添加/获取操作

- (void)addOperationWithBlock:(void (^)(void))block;向队列中添加一个 NSBlockOperation 类型操作对象。

- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait;向队列中添加操作数组,wait 标志是否阻塞当前线程直到所有操作结束

- (NSArray *)operations;当前在队列中的操作数组(某个操作执行结束后会自动从这个数组清除)。

- (NSUInteger)operationCount;当前队列中的操作数。

获取队列

+ (id)currentQueue;获取当前队列,如果当前线程不是在 NSOperationQueue 上运行则返回 nil。

+ (id)mainQueue;获取主队列。

附加知识:

队列组  dispatch_group_t

当把队列任务添加进队列组的时候  当所有添加的任务完成的时候  会有通知回调dispatch_group_notify 

实际应用案例(下载两张图片,当两张图都下载完成的时候 就行拼接得出新的图片)

实现步骤如下:

1.创建一个队列组:

2.在全局队列异步中添加一个任务(下载image1),并添加进队列组

3.在全局队列中异步添加一个任务(下载image2),并添加进队列组

4.当都下载完成的时候  进行回调dispatch_group_notify (这时候就行图片拼接)


dispatch_barrier_async   栅栏函数:

栅栏函数,使用此方法创建的任务,会查找当前队列中有没有其他任务要执行,如果有,则等待已有任务执行完毕后再执行,同时,在此任务之后进入队列的任务,需要等待此任务执行完成后,才能执行

相关文章

  • 关于多线程的理解(不定时更新)

    下面会以一小个一小个的知识点进行表达(可能想到哪就写到哪) 1.每一个程序都相当于一个进程,每个进程,系统都会为其...

  • 完结

    关于多线程并发编程,先写到这里,后面可能继续插入更新。

  • 关于多线程的理解

    1.关于多线程存在的意义: 首先,既然有多线程,存在既有意义,那么为什么存在多线程呢,多线程的用处在何处呢我的理解...

  • 关于多线程的理解

    前言 线程是用来执行任务的,线程彻底执行完任务A才能去执行任务B。为了同时执行两个任务,产生了多线程。 1、什么是...

  • OC-多线程GCD

    参考:GCD源码深入理解 GCDiOS多线程--彻底学会多线程之『GCD』关于iOS多线程,我说,你听,没准你就懂...

  • Springboot配置多线程定时任务Schedule

    一.为什么需要配置多线程定时任务& 多线程定时任务的配置使用场景 springboot中通过注解 @Schedul...

  • 5. 邮件定时发送

    1.生活中的定时任务 定时推送,签到 QQ定时发说说邮件 蚂蚁森林定时产生能量。微信公众号不步数的更新 手机定时开...

  • 使用SpringBoot快速实现定时任务

    定时任务在我们开发中是广泛存在的,定时任务在初期我一般是直接利用多线程来实现,对于新手来说比较的复杂也不容易理解。...

  • 线程通讯详解

    关于子线程能否更新UI的思考线程通讯详解线程池-多线程的高效使用姿势 上文我们说到了关于子线程中能否更新UI的问题...

  • 使用PHP代码实现计划任务

    参考PHP实现执行定时任务的几种思路详解 PHP本身是没有定时功能的,这主要是因为PHP无法实现多线程。所谓多线程...

网友评论

    本文标题:关于多线程的理解(不定时更新)

    本文链接:https://www.haomeiwen.com/subject/aywvtqtx.html