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) ...
随机推荐
- 倍福TwinCAT(贝福Beckhoff)基础教程5.1 TwinCAT-1 获取和设置系统时间
使用功能块NT_GetTime,NETID填写两个单引号表示本机,START就是一个触发信号,一般的功能块都需要一个上升沿触发执行,最后的输出类型都是让系统自己决定,然后统一把这些变量放到全局变量中( ...
- 倍福TwinCAT(贝福Beckhoff)基础教程2.2 TwinCAT常见类型使用和转换_数组
声明和实例化数组的方法如下,你可以声明各种基本类型的数组 i: INT; array1: ARRAY [0..500] OF INT; FOR i := 0 TO 5000 DO arra ...
- Time.fixedDeltaTime 固定增量时间
static var fixedDeltaTime : float Description描述 The interval in seconds at which physics and other f ...
- Linux——Django 开发环境部署(二)python版本控制器pyenv
python版本控制器pyenv 之前的 那篇是说明了django环境的site package完全独立出来了,但是使用的python解释器还是系统的,为了继续独立出来,甚至是达到ruby的rvm的自 ...
- python——type()创建类
今天我算是长知识了,我是一个python菜鸟,以前一直认为type(A)可以返回A的类型,但是不知道type还可以用于创建class,这篇经验就是介绍一下如何用type()创建一个类,以及如何设置该类 ...
- react-native 常用组件的用法(二)
ScrollView组件 能够调用移动平台的ScrollView(滚动视图)的组件,同时还集成了触摸锁定的“响应者”系统.注意一定要给scrollview一个高度,或者是他父级的高度. 常用方法 on ...
- mongoDB: cursor not found on server
查询mongoDB集合数据更新,数据有400w多.我一次用cursor(游标)取1w,处理更新.程序在某段时间运行中遍历游标时发生异常! DBCursor cursor = tabColl.find( ...
- vim命令行模式
1. 激活命令行模式 : 进入命令行模式 <Esc> 退出命令行模式 2. 常用命令 :p 打印 (:print) :e 读入文件 (:edit) :w 写入文件 (:write) :t ...
- Wd 西部数据
西部数据 https://item.jd.com/3564471.html#none 打算买一个大硬盘记录代码片段.开发项目.开发工具.电影游戏等…… /** * 获取100天后的日子 * 用来做计划 ...
- IDEA下配置Spring Boot的热部署
© 版权声明:本文为博主原创文章,转载请注明出处 devtools简介 spring-boot-devtools会监听classpath下的文件变动,并且会立即重启应用(发生在保存时机),因为其采用的 ...