一、线程概述

1、 iOS里面的线程按种类可分为同步线程和异步线程。同步线程指调用同步线程的地方必须等到同步线程运行完成才干够继续向下运行。而调用异步线程的地方则在运行完调用异步线程的语句后就能够继续向下运行。

2、线程按调用方式又能够大致分为下面几种类型:NSObject、NSThread、NSOperation和GCD。

NSObject和NSThread仅仅能管理单个的线程。功能较简单。GCD和NSOperation则能够进行队列等复杂操作。且效率较高。当中GCD方式最为有效,NSOperation是基于GCD封装的,功能相对来说更丰富。

3、异步线程中往往要创建自己的自己主动释放池来释放异步线程中创建的自己主动释放对象。

4、异步线程中有须要的话,要做自己的异常捕捉处理。由于当异步线程中产生异常时,主线程非常有可能会捕捉不到异步线程抛出的异常。

二、线程调用

1、NSObject

*        线程创建

NSObjcet对象自身实现了performSelectorInBackground、performSelectorOnMainThread和performSelector:onThread:withObject:等线程相关方法。

1.1 performSelectorInBackground是创建一个异步线程

-(void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait :

aSelector是在主线程中运行的方法,arg是传递的參数。wait指是否要等待aSelector运行完成。

1.2 performSelectorOnMainThread是返回主线程运行相关方法

-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait:

aSelector是在主线程中运行的方法。arg是传递的參数,wait指是否要等待aSelector运行完成。

1.3 performSelector:onThread:withObject:是运行某个特定线程中的方法

-(void)performSelector:(SEL)aSelector onThread:(NSThread *) withObject:(id)arg waitUntilDone:(BOOL)wait:

该方法一般用于线程间相互通信,即在一个线程中发送消息给还有一个线程

注:每个线程都有自己的RunLoop,但非主线程的RunLoop默认是关闭的,当须要进行非主线程的通信时,须要确保通信线程的RunLoop是开启的,否则发送给通信线程的消息不会被运行。

1.4 -(void)performSelector:withObject:afterDelay:是指在当前线程延迟运行某个方法

*     线程的暂停、继续和取消

NSObject是无法暂停和取消线程的。

2、NSThread

*     线程创建

NSThread有两种创建线程的方式: detachNewThreadSelector和initWithTarget.

2.1 detachNewThreadSelector:toTarget: withObject:

调用这样的方法创建的线程会主动执行。不须要手动启动。

2.2 initWithTarget: selector:objcet:

调用这样的方式新建一个线程,新建完毕后须要调用NSThread的start方法来启动线程。

*     线程的取消

调用NSThrea的cancel方法就可以取消线程,但正在运行的线程不会立即结束。所以NSThread的cancel方法的实质意义是把线程的状态设置为已取消,然后编代码时就能够依赖线程的状态去结束掉线程。

*     线程的暂停和继续

NSThread没有提供暂停的方法

3、NSOperation

*      线程创建

NSOperation通常和NSOperationQueue配对使用,创建好NSOperation对象后加入到NSOperationQueue中,NSOperationQueue就可以为我们管理NSOperation。包含为NSOperation配置异步线程和启动等。

NSOperationQueue按类型分为:主队列和自己定义队列。

主队列执行在主线程上。而自己定义队列在后台执行。主队列获取方式:[NSOperationQueue mainQueue];自己定义队列获取方式:[[NSOperationQueue alloc] init]。

NSOperation按类型分为:NSOperation、NSBlockOperation和NSInvocationOperation。

3.1 NSOperation:

NSOperation是一个虚类,我们须要继续NSOperation来创建子类,并重写main方法或start方法。重写main方法非常easy,仅仅须要重写好main方法,不须要管理一些状态属性(如isExecuted和isFinished),当main方法返回就假定操作结束了;而重写start方法则更灵活,拥有很多其它的控制权,可是状态属性信息则须要自己控制。

3.2 NSBlockOperation:

NSBlockOperation是调用blockOperationWithBlock方法以一个block作为參数创建的一个operation对象,而且在对象实例化后还能够调用addExecutionBlock方法动态加入block,但加入动作须要在operation运行前发生,通常也就是在operation加入到NSOperationQueue前。否则非常可能产生异常和莫名错误。NSBlockOperation的业务逻辑操作主要写在block中。

3.3 NSInvocationOperation:

NSInvocationOperation是以一个SEL方法或NSInvocation为參数初始化的operation对象。NSInvocationOperation的业务逻辑操作主要放在相应的SEL方法或NSInvocation对象中。

*     线程的暂定和继续

调用NSOperationQueue对象的setSuspended:YES就可以暂停NSOperationQueue中待运行线程的运行,然后调用setSuspended:NO就可以继续运行。

*     线程的取消

调用NSOperation对象的cancel方法会取消单个NSOperation对象的运行,而调用NSOperationQueue对象的cancelAllOperation方法会取消NSOperation队列中全部对象的运行。

*     线程依赖

假设NSOperation对象有运行顺利要求的话,比方operationB须要在operationA运行完成后才干够运行,那就能够通过设置NSOperation之间的依赖关系来实现:[operationB addDependency:operationA]。

*     手动运行

假设NSOperation不和NSOperationQueue配对使用,这时就须要调用NSOperation的start方法来运行NSOperation,通常要重写isExecuting,isFinished,start和main等方法,假设要实现并发操作,则还要重写isConcurrent方法。假设NSOperation间有依赖关系,则还要重写isReady方法。

示比例如以下:

@interface HandOperation(){

BOOL executing; // 是否正在运行

BOOL finished;//  是否运行结束

}

-(void)completeOperation;// 结束后的状态处理方法

@end

@implementation HandOperation

#pragma mark - Lifecycle Methods

-(id)init{

self = [super init];

if(self){

executing = NO;

finished = NO;

}

return self;

}

-(BOOL)isConcurrent{

return YES;

}

-(BOOL)isExecuting{

return executing;

}

-(BOOL)isFinished{

return finished;

}

-(BOOL)isReady{

return [super isReady];

}

-(void)start{

if([self isCancelled]){

[self willChangeValueForKey:@“isFinished”];

finished = YES;

[self didChangeValueForKey:@“isFinished”];

return;

}

[self willChangeValueForKey:@“isExecuting”];

executing = YES;

[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];

[self didChangeValueForKey:@“isExecuting”];

}

-(void)main{

@try{

@autoraleasepool{

[self handleForTask];

}

[self completeOperation];

}

@catch(NSException *exception){

}

@finally{

}

}

#pragma mark - Custom Methods

-(void)completeOperation{

[self willChangeValueForKey:@“isFinished”];

[self willChangeValueForKey:@“isExecuting”];

executing = NO;

finished = YES;

[self didChangeValueForKey:@“isExecuting”];

[self didChangeValueForKey:@“isFinished”];

}

//业务处理方法

-(void)handleForTask{

for(int i=0;i<10;i++){

if(![self isCancelled]){

NSLog(@“%s %i”,__func__,i);

sleep(1);

}

}

}

4、GCD

*     线程创建

GCD是Grand Central Dispatch的缩写。是Apple开发的一个多核编程的解决方式。GCD一般是把block以dispatch_async或dispatch_sync的方式加入到dispatch_queue_t队列中来创建线程: dispatch_async(dispatch_queue_t queue ,dispatch_block
block)。

dispatch_async为异步加入,等dispatch_async语句运行完成后就可以继续运行下去;而dispatch_sync为同步加入,须要等dispatch_sync加入的block内容运行完成后才干够继续向下运行。

dispatch_queue_t分为三种类型: Serial Queues、Main Queues和Concurrent Queues。

4.1 Serial Queues

Serial Queues称为串行队列,Serial Queues队列中的任务仅仅能顺序运行,一次运行一个。我们能够在Serial Queues中运行有依赖关系的任务或同步任务。

Serial Queues队列之间是能够并发运行的。

Serial Queues是通过dispatch_queue_create(“testQueue”,NULL)语句创建的,“testQueue”是队列标识符。NULL相应一个表示队列属性的參数,仅仅要传入NULL或DISPATCH_QUEUE_SERIAL就可以获取一个串行队列。

4.2 Main Queues

Main Queues 称为主线程队列,全部提交至Main Queues中的任务都会在主线程中运行,所以Main Queues也是一个串行队列。

Main Queues能够通过dispatch_get_main_queue()语句获取到,Main Queues是全局性的队列。

4.3 Concurrent Queues

Concurrent Queues称为并行队列,全部提交至Concurrent Queues中的任务都是并行运行的。Concurrent Queues又分为Global Queues和User Concurrent Queues。Global Queues由系统依据优先级提供四个不同的dispatch queue。

Global Queues能够通过dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags)语句获取到。priority是优先级,优先级有DISPATCH_QUEUE_PRIORITY_HIGH、DISPATCH_QUEUE_PRIORITY_DEFAULT、DISPATCH_QUEUE_PRIORITY_LOW、DISPATCH_QUEUE_PRIORITY_BACKGROUND四种:flags是保留字段,现阶段传入0就可以。

User Concurrent Queues是通过dispatch_queue_create(“testQueue”,DISPATCH_QUEUE_CONCURRENT)语句创建的,“testQueue”是队列标识符,DISPATCH_QUEUE_CONCURRENT表示队列为并行队列。

*     线程的暂停和继续

调用dispatch_suspend(dispatch_queue_t)就可以挂起队列。使队列中待运行的任务暂停运行,但正在运行的任务还是会继续运行。

调用dispatch_resume(dispatch_queue_t)即能够使挂起的队列继续运行。

dispatch_suspend 和 dispatch_resume仅仅对Serial Queues 和 User Concurrent Queues有效,由于Main Queues 和Global Queues都是全局队列。

*     线程的取消

GCD中没有显式的线程取消方法调用。仅仅能在代码中依据预先设置的标志位去实现取消操作。

*     dispatch_group_async的使用

dispatch_group_async能够实现监听一组任务是否完毕,完毕后得到通知运行其它操作。

使用dispatch_group_async加入一组任务后。能够使用dispatch_group_wait方法同步等待所有任务运行完成,然后才运行之后的其它任务;也能够使用dispatch_group_notify异步监听前面的任务,等前面任务运行完成后触发dispatch_group_notify中的处理事件。

例如以下:

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group,globalQueue,^{

@autoreleasepool{

for(int i=0;i<5;i++){

NSLog(@“001 %i”,i);

sleep(1);

}

}

});

dispatch_group_async(group,globalQueue,^{

@autoreleasepool{

for(int i=0;i<5;i++){

NSLog(@“002 %i”,i);

sleep(1);

}

}

});

dispatch_group_wait(group,DISPATCH_TIME_FOREVER);

/*

dispatch_group_notify(group,globalQueue,^{

@qutoreleasepool{

NSLog(@“notify End”);

}

});

*/

dispatch_release(group);

*     dispatch_barrier_async的使用

dispatch_barrier_async是在前面的任务运行结束后它才运行,并且它后面的任务等它运行完毕后才运行。

dispatch_barrier_async(dispatch_queue_t queue,dispatch_block_t block),queue必须是自己定义的并行队列,假设是其它队列,那么dispatch_barrier_async的效果和dispatch_sync是同样的。

*     dispatch_apply 的使用

dispatch_apply能够运行某个代码片段N次,能够用在相互间没依赖关系的并行计算等。代码例如以下:

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_PRIORITY_DEFAULT,0);

__block int sum = 0;

dispatch_apply(10,globalQueue,^(size_t i){

sum += i;

});

Demo下载链接:http://download.csdn.net/download/changyou0730/7427215

iOS线程浅析的更多相关文章

  1. IOS 线程处理 子线程

    IOS 线程处理 子线程的启动与结束 技术交流新QQ群:414971585   IOS中,如果要在主线程中启动一个子线程,可以又两种方法: [NSThread detachNewThreadSelec ...

  2. IOS 网络浅析-(十三 SDWebImage 实用技巧)

    IOS 网络浅析-(十三 SDWebImage 实用技巧) 首先让我描述一下为了什么而产生的实用技巧.(在TableView.CollectionView中)当用户所处环境WiFi网速不够快(不能立即 ...

  3. iOS线程之——NSCondition

    多线程在各种编程语言中都是难点,很多语言中实现起来很麻烦,objective-c虽然源于c,但其多线程编程却相当简单,可以与java相媲美.这篇文章主要从线程创建与启动.线程的同步与锁.线程的交互.线 ...

  4. iOS 线程操作库 PromiseKit

    iOS 线程操作库 PromiseKit 官网:http://promisekit.org/ github:https://github.com/mxcl/PromiseKit/tree/master ...

  5. c# 线程浅析(代理 、Invoke、Lock)

    前言:本来想根据自己的经验总结一下c#线程相关的知识点, 写之前看了一些其他人的博客,发现自己也就掌握了不到三分之一....希望通过这次的博客将自己的知识点补充一下,写出更直白的博客和初学者分享. 这 ...

  6. IOS RunLoop浅析 三

    经过两篇的介绍我想对RunLoop应该有了简单的了解,至少不至于一无所知. 在这篇我想对“CFRunLoopObserverRef”做一下简单的补充. 在补充之前先说一下. 在现在的开发中已经很少见到 ...

  7. IOS RunLoop浅析 二

    上一篇我们说了runloop 的几种模式,那么我们在模式中又要做些什么呢??? 模式中有三个模块: 事件源(输入源) Source Source: 按照官方文档分类 Port-Based Custom ...

  8. ios线程和GCD

    1.什么是进程? 进程是指在系统中正在运行的一个应用程序.比如同时打开QQ.Xcode,系统就会分别启动2个进程.截图 2.什么是线程? 1).一个进程要想执行任务,必须得有线程(每一个进程至少要有一 ...

  9. iOS - 线程管理

    iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...

随机推荐

  1. EffectiveJava(7)避免使用终结方法

    避免使用终结方法 1.使用终结方法会导致行为不稳定,性能降低,以及可移植性的问题.(终结线程的优先级过低) 终结方法不能保证被及时的执行(从一个对象变得不可到达开始,到中介方法被执行,所花费的时间是任 ...

  2. charles抓https包

    Charles是一款非常好用的抓包工具,有Window,Linux,Mac OS三个版本,个人觉得比shark和TCPDump好用多了. 闲话不多说,公司将服务从http转到https,导致今天因为抓 ...

  3. OpenCV入门学习(三)HistogramEquivalent

    直方图均衡 #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include & ...

  4. 浅谈JavaScript变量声明提升

    前段时间阿里实习生内推,一面就被刷了,也是郁闷.今天系统给发通知,大致意思就是内推环节不足以了解彼此,还可以参加笔试,于是赶紧再投一次.官网流程显示笔试时间3月31日,时间快到了,开始刷题.网上搜了一 ...

  5. 阿里巴巴 DevOps 转型后的运维平台建设

    原文:http://www.sohu.com/a/156724220_262549 本文转载自公众号「DevOps 时代」,高效运维社区致力于陪伴您的职业生涯,与您一起愉快的成长. 作者简介: 陈喻( ...

  6. window.location网页URL信息

    window.location属性 描述 hash 设置或获取 href 属性中在井号“#”后面的分段. host 设置或获取 location 或 URL 的 hostname 和 port 号码. ...

  7. docker pull net/http: TLS handshake timeout错误解决

    docker pull  net/http: TLS handshake timeout  出现这个错误,原因很明显,我们在围城里,有两种解决办法,一种是用梯子爬围墙,一种是用国内源,下面用国内源 e ...

  8. different between method and function

    A method is on an object. A function is independent of an object. For Java, there are only methods. ...

  9. vbox克隆虚拟机,网卡启动报错“Device eth0 does not seem to be present”

    vbox克隆虚拟机,网卡启动报错"Device eth0 does not seem to be present". 须要看以下三个地方:确保文件名称,设备名.mac地址都一致. ...

  10. 莫小安 CentOS7使用firewalld打开关闭防火墙与端口

    1.firewalld的基本使用 启动: systemctl start firewalld 查看状态: systemctl status firewalld  停止: systemctl disab ...