iOS线程浅析
一、线程概述
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线程浅析的更多相关文章
- IOS 线程处理 子线程
IOS 线程处理 子线程的启动与结束 技术交流新QQ群:414971585 IOS中,如果要在主线程中启动一个子线程,可以又两种方法: [NSThread detachNewThreadSelec ...
- IOS 网络浅析-(十三 SDWebImage 实用技巧)
IOS 网络浅析-(十三 SDWebImage 实用技巧) 首先让我描述一下为了什么而产生的实用技巧.(在TableView.CollectionView中)当用户所处环境WiFi网速不够快(不能立即 ...
- iOS线程之——NSCondition
多线程在各种编程语言中都是难点,很多语言中实现起来很麻烦,objective-c虽然源于c,但其多线程编程却相当简单,可以与java相媲美.这篇文章主要从线程创建与启动.线程的同步与锁.线程的交互.线 ...
- iOS 线程操作库 PromiseKit
iOS 线程操作库 PromiseKit 官网:http://promisekit.org/ github:https://github.com/mxcl/PromiseKit/tree/master ...
- c# 线程浅析(代理 、Invoke、Lock)
前言:本来想根据自己的经验总结一下c#线程相关的知识点, 写之前看了一些其他人的博客,发现自己也就掌握了不到三分之一....希望通过这次的博客将自己的知识点补充一下,写出更直白的博客和初学者分享. 这 ...
- IOS RunLoop浅析 三
经过两篇的介绍我想对RunLoop应该有了简单的了解,至少不至于一无所知. 在这篇我想对“CFRunLoopObserverRef”做一下简单的补充. 在补充之前先说一下. 在现在的开发中已经很少见到 ...
- IOS RunLoop浅析 二
上一篇我们说了runloop 的几种模式,那么我们在模式中又要做些什么呢??? 模式中有三个模块: 事件源(输入源) Source Source: 按照官方文档分类 Port-Based Custom ...
- ios线程和GCD
1.什么是进程? 进程是指在系统中正在运行的一个应用程序.比如同时打开QQ.Xcode,系统就会分别启动2个进程.截图 2.什么是线程? 1).一个进程要想执行任务,必须得有线程(每一个进程至少要有一 ...
- iOS - 线程管理
iOS开发多线程篇—GCD的常见用法 一.延迟执行 1.介绍 iOS常见的延时执行有2种方式 (1)调用NSObject的方法 [self performSelector:@selector(run) ...
随机推荐
- [阿里Hao]Android无线开发的几种经常使用技术
本文由阿里巴巴移动安全client.YunOS资深project师Hao(嵌入式企鹅圈原创团队成员)撰写,是Hao在嵌入式企鹅圈发表的第一篇原创文章.对Android无线开发的几种经常使用技术进行综述 ...
- AndroidStudio短信验证功能收不到验证码
http://mob.com/第三方接口获取地址: 登陆过后点我的后台即可上传,管理应用.需注意的是,即使验证不通过,只要整合了短信验证的Jar包,每天都有20条免费验证短信.现在的mob.com只支 ...
- Windows无法删除文件 提示找不到该项目怎么办
1 如图所示,我想要删除某个文件,提示如图所示,一般用360的强力删除也不管用. 2 在桌面新建一个文本文档,并输入以下内容.保存为bat格式(比如Delete.bat).然后把这个删不掉的文件拖 ...
- x^2 + (y-(x^2)(1/3))^2 = 1 心形方程 5.20无聊之作
2017.05.20 一个无聊的周六,只能看别人秀恩爱.偶然间在网上看到一个有意思的方程 x^2 + (y-(x^2)(1/3))^2 = 1,据说这个方程可以绘制出一个爱心的形状.既然很无聊,就随便 ...
- urlib2 标准代码
import urllib2 def downloadHtml(url,user_agent=None,num_retries=2): print 'Downloading:',url headers ...
- mysql_affected_rows的注意点
取得最近一次与 link_identifier 关联的 INSERT,UPDATE 或 DELETE 查询所影响的记录行数. 1.执行成功,则返回受影响的行的数目,如果最近一次查询失败的话,函数返回 ...
- object-c 框架之经常使用结构体
Foundation 框架定义经常使用结构体.结构体採用object-c 定义:经常使用NSSRange,NSPoint.NSSize,NSRect等 一.NSRange 创建范围结构体. 方法:NS ...
- Nginx:管理HTTP模块的配置项
参考资料<深入理解Nginx> 一个nginx.conf的例子 http { mytest_num ; server { server_name A; listen ; mytest_nu ...
- 【Excle数据透视表】如何为一个字段添加多种分类汇总方式
解决方案1 右键单击人员分类字段包含的任意单元格→右键→字段设置→自定义→(最大值.最小值) 解决方案2 单击人员分类→分析→字段设置
- HTML to PDF pechkin
1. Goto Nuget 下载 Pechkin 控件 2. 创建需要打印的的PDF controller 和 Action, 这里会调用其他页面的内容进行打印. public ActionResul ...