一、线程概述

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. 【Excle数据透视表】如何按照地区交替填充背景颜色

    现存在如下数据透视表 需要根据地区填充不同的背景颜色 步骤 选定数值区域→开始→条件格式→新建规则,出现如下窗口: 公式:=MOD(COUNT(1/(MATCH($A$4:$A4,$A$4:$A4,) ...

  2. [转]Tomcat工作原理详解

    一.Tomcat背景 自从JSP发布之后,推出了各式各样的JSP引擎.Apache Group在完成GNUJSP1.0的开发以后,开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JS ...

  3. Linux下Nagios的安装与配置(转载)

    一.Nagios简介 Nagios是一款开源的电脑系统和网络监视工具,能有效监控Windows.Linux和Unix的主机状态,交换机路由器等网络设置,打印机等.在系统或服务状态异常时发出邮件或短信报 ...

  4. asp.net core mvc视频A:笔记1.基本概念介绍

    此笔记来自视频教程 MVC本身与三层架构没有联系 使用VS2017新建一个默认的asp.net core mvc网站,认识结构及文件用途.

  5. PHP array_walk() 函数

    定义和用法 array_walk() 函数对数组中的每个元素应用用户自定义函数.在函数中,数组的键名和键值是参数. <?php function myfunction($value,$key,$ ...

  6. Spring事务管理简介

    © 版权声明:本文为博主原创文章,转载请注明出处 1.什么是事务 - 事务是指逻辑上的一组操作,这组操作要么全部成功,要么全部失败 2.事务特性(ACID) - 1.原子性(Atomicity):指事 ...

  7. Ubuntu 16.04主题美化和软件推荐

    http://www.linuxidc.com/Linux/2016-09/135165.htm http://www.techweb.com.cn/network/system/2015-11-20 ...

  8. Shell计算器

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

  9. 局域网简单的SVN服务器的搭建

            最近组织在做一个比较大的项目,需要多人参与配合,经常会对项目文件增删查改,因此使用了SVN作为项目管理工具.但大家都很"盲",所以搭建SVN服务器的任务就落在了我这 ...

  10. linux设备驱动的分层设计思想--input子系统及RTC

    转自:linux设备驱动的分层设计思想 宋宝华 http://blog.csdn.net/21cnbao/article/details/5615493 1.1 设备驱动核心层和例化 在面向对象的程序 ...