文章标题

来源:互联网 发布:js省市区三级联动 编辑:程序博客网 时间:2024/06/07 12:09

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];

0 0
原创粉丝点击