您的位置:首页 > 其它

文章标题

2015-10-14 21:21 260 查看

iOS三种多线程技术介绍

简介

1.NSThread 每个NSThread对象对应一个线程,量级较轻(真正的多线程)

2.以下两点是苹果专门开发的“并发”技术,使得程序员可以不再去关心线程的具体使用问题

ØNSOperation/NSOperationQueue 面向对象的线程技术

ØGCD —— Grand Central Dispatch(派发) 是基于C语言的框架,可以充分利用多核,是苹果推荐使用的多线程技术

以上这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的,在项目中很多框架技术分别使用了不同多线程技术。

优缺点

•NSThread:

–优点:NSThread 比其他两个轻量级,使用简单

–缺点:需要自己管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有一定的系统开销

•NSOperation:

–不需要关心线程管理,数据同步的事情,可以把精力放在自己需要执行的操作上

–NSOperation是面向对象的

•GCD:

–Grand Central Dispatch是由苹果开发的一个多核编程的解决方案。iOS4.0+才能使用,是替代NSThread, NSOperation的高效和强大的技术

–GCD是基于C语言的

NSThread

第一种方法:

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

调用立即创建一个新线程执行操作

第二种方法:

NSThread* myThread = [[NSThread alloc] initWithTarget:self selector:@selector(myThreadMethod:) object:nil];

[myThread start];

NSThread初始化之后,新的线程并没有执行,而是调用 start 时才会创建线程执行。这种方法相对上面的方法更加灵活,在启动新的线程之前,对线程进行相应的操作,比如设置优先级,加锁NSCondition。

第三种方法:

[myObject performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil];

利用 NSObject 的类方法 performSelectorInBackground:withObject: 来创建一个线程:

总结:

以上都可以在新的线程中调用performSelectorOnMainThread: withObject:waitUntilDone:更新UI,因为子线程不能直接更新UI。

NSOperationQueue

第一种方法

NSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];

[oprationQueue addOperationWithBlock:^{

//这个block语句块在子线程中执行

NSLog(@”oprationQueue”);

}];

[oprationQueue release];

第二种方法

NSOperationQueue *oprationQueue1 = [[NSOperationQueue alloc] init];

oprationQueue1.maxConcurrentOperationCount = 2;

//指定池子的并发数

NSInvocationOperation *invocation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(snippet) object:nil];

NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

[self snippet];

}];

[oprationQueue1 addOperation:invocation];//将任务添加到池子里面,可以给池子添加多个任务,并且指定它的并发数

[oprationQueue1 addOperation:blockOperation];

[invation release];

总结:第二种跟第一种比,设置了池子的并发数,即每次从池子里拿出几条去执行,NSOperation是个抽象类,所以不能直接创建,要用他的子类进行创建,上面两种写的是系统给的子类,还有一种是自己创建一个类继承NSOperation.

GCD

/* GCD:大调度中心

* 函数级别,效率高,推荐使用

* 原理:有一个队列,队列中是代码段任务(任务的创建是用block或者函数)

* 队列,可以自定义队列,也可以使用系统的队列

* 队列分:穿行和并行(并发)两种

*/

先介绍一些基础:

1> 要使用GCD,所有的方法都是dispatch开头的

2> 名词解释

global 全局

queue 队列

async 异步

sync 同步

3> 要执行异步的任务,就在全局队列中执行即可

dispatch_async 异步执行控制不住先后顺序

4> 关于GCD的队列

全局队列 dispatch_get_global_queue

例子

/* 1.创建一个串行调度队列,穿行即:任务一个一个执行 */

dispatch_queue_t myQueue = dispatch_queue_create(“com.myQueue.www”, DISPATCH_QUEUE_SERIAL);

/* 2.调度队列中添加任务 */

dispatch_async(myQueue, ^{

NSLog(@”GCD”);

}) ;

/* 创建自定义并发调度队列 */

dispatch_queue_t MyConQueue = dispatch_queue_create(“com.myConQueue.www”, DISPATCH_QUEUE_CONCURRENT);

dispatch_async(MyConQueue, ^{

NSLog(@”GCD”);

});

上面两个不太常用 一般都是用系统的串行和并行

/*

* 系统有一个串行队列:main,即主线程

* 有四个并发队列:high,default,low,background,通常使用default

*/

dispatch_queue_t mainQueue = dispatch_get_main_queue();

/* 向调度队列添加任务 */

dispatch_async(mainQueue, ^{

NSLog(@”GCD”);

});

/* 系统的并发队列 */

dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

/* 调度队列中添加任务 */

dispatch_async(global, ^{

NSLog(@”GCD”);

});

一个实际例子

/* 子线程负责数据的加载

* 主线程负责 刷新 等操作

*/

dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_async(global, ^{

NSString *str = @”http://e.hiphotos.baidu.com/image/pic/item/42a98226cffc1e1786934a384890f603738de98f.jpg“;

NSURL *url = [NSURL URLWithString:str];

NSData *data = [NSData dataWithContentsOfURL:url];

UIImage *image = [UIImage imageWithData:data];

/* 回到主线程队列,添加任务(刷新任务) */

dispatch_async(dispatch_get_main_queue(), ^{

self.imageView.image = image;

});

});

延迟执行

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

NSLog(@”GCD”);

});

补充

1.多线程之间进行通讯;

在应用程序主线程中做事情:

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

(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array

在指定线程中做事情:

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

(void)performSelector:(SEL)aSelector onThread:(NSThread )thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray )array

在当前线程中做事情:

//Invokes a method of the receiver on the current thread using the default mode after a delay.

(void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay

performSelector:withObject:afterDelay:inModes:

取消发送给当前线程的某个消息

cancelPreviousPerformRequestsWithTarget:

cancelPreviousPerformRequestsWithTarget:selector:object:

2.GCD创建单例方法

static ViewController *vc = nil;

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

vc = [[ViewController alloc] init];

});

return vc;

3.主线程界面更新代码

如在我们在某个线程中下载数据,下载完成之后要通知主线程中更新界面等等,可以使用如下接口:- (void)myThreadMainMethod

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// to do something in your thread job



[self performSelectorOnMainThread:@selector(updateUI) withObject:nil waitUntilDone:NO];

[pool release];
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: