一、线程概述

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. Material Design (二),TextInputLayout的使用

    前言  一般登录注冊界面都须要EditText这个控件来让用户输入信息,同一时候我们通常会设置一个标签(使用TextView)和EditText的hint属性来提示用户输入的内容,而设计库中高级组件T ...

  2. 基于WPF系统框架设计(2)-Fluent Ribbon之HelloWorld

    Fluent/Ribbon是微软在其最新桌面操作系统Windows 7中使用的图形用户界面. Windows平台的进化,伴随着系统图形界面的重新设计.从Windows XP到Windows Vista ...

  3. 小tip: base64:URL背景图片与web页面性能优化

    转自:http://www.zhangxinxu.com/wordpress/?p=2341 一.base64百科 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,可用于在HTTP ...

  4. 倍福TwinCAT(贝福Beckhoff)基础教程4.2 TwinCAT如何读写CSV文件

    本程序只是在官方范例程序上稍作修改,在官方原有的范例中,演示了多种模式的读写(可以认为CSV文件是比TXT文件需要更多数据量的时候使用,比如记录一个小型的数据库集合)   但是写的比较混乱,甚至没有H ...

  5. 倒计时:CountDownLatch(火箭发射前的准备)读书笔记

     这是一个非常实用的多线程控制工具类,经典的场景就是 火箭发射,在火箭发射前,为了保证万无一失,往往还要进行各项设备,仪器的检查,只有等待所有的检查完毕后,引擎才能点火,      CountDown ...

  6. MPTCP 理解

    背景      随着技术的发展许多设备具有了多个网络接口,而TCP依然是一个单线路的协议,在TCP的通信过程中发端和收端都 不能随意变换地址.我们可以利用多个网络接口的这一特性来改善性能和有效冗余.例 ...

  7. 不得不看的Java代码性能优化总结

    原文:https://blog.csdn.net/mr_smile2014/article/details/50112723 前言 代码优化,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么 ...

  8. Shell计算器

    #!/bin/bash # filename : jisuan.sh # description : add, subtract, multiply, and divide print_usage() ...

  9. spring boot 使用拦截器 实现 用户登录拦截

    登录拦截和和权限拦截实现类似   首先自定义一个[DefineAdapter]类,这个类我是用来放自定义的配置(比如 自定义请求参数,自定义拦截器等),集成WebMvcConfigurerAdapte ...

  10. 转:什么是Node.js?

    Node不是万能药!但的确能解决一些关键问题 学习Node不是一件轻松事儿,但你所收到的回报是对得起你的付出的.因为当下Web应用开发中的诸多难题唯有JavaScript才能解决. 目录 专家们的警告 ...