IOS开发-多线程编程技术(Thread、Cocoa operations、GCD)

前言:在软件开发中,多线程编程技术被广泛应用,相信多线程任务对我们来说已经不再陌生了。有了多线程技术,我们可以同做多个事情,而不是一个一个任务地进行。比如:前端和后台作交互、大任务(需要耗费一定的时间和资源)等等。也就是说,我们可以使用线程把占据时间长的任务放到后台中处理,而不影响到用户的使用。

线程的定义:

每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。也可以把它理解为代码运行的上下文。所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务。通常由操作系统负责多个线程的调度和执行。

转自百度百科:多线程

IOS支持的多线程技术:

一、Thread:

1)显式创建线程:NSThreed

2)隐式创建线程:NSObject

二、Cocoa operations:

NSOperation类是一个抽象类,因为我们必须使用它的两个子类。

  1)NSInvocationOperation

2)NSBlockOperation

————————————————————————————

3)NSOperationQueue(继承于NSObject)

三、Grand Central Dispatch (GCD):

1)GCD的创建

2)重复执行线程:dispatch_apply

3)操作队列:dispatch_queue_create

4)GCD群组通知:dispatch_group_t

5)GCD实现计时器

一、Thread

我们可以使用NSTherad或NSObject类去调用:

1)显式创建线程:NSThread

创建NSThread有两个办法

1.1)创建之后需要使用start方法,才会执行方法:

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

1.2)创建并马上执行方法:

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

2)隐式创建线程:NSObject

我们也可以使用NSObject类的方法直接调用方法

[self performSelectorInBackground:@selector(threadAlloc) withObject:nil];

NSThread相关属性及方法:

// 获取/设置线程的名字
@property (copy) NSString *name NS_AVAILABLE(10_5, 2_0);

/**
 *  获取当前线程的线程对象
 *
 *  通过这个属性可以查看当前线程是第几条线程,主线程为1。
 *  可以看到当前线程的序号及名字,主线程的序号为1,依次叠加。
 */
+ (NSThread *)currentThread;

// 线程休眠(秒)
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;

// 线程休眠,指定具体什么时间休眠
+ (void)sleepUntilDate:(NSDate *)date;

// 退出线程
// 注意:这里会把线程对象销毁!销毁后就不能再次启动线程,否则程序会崩溃。
+ (void)exit;

二、Cocoa operations

1)NSInvocationOperation

// 创建线程任务
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

// 线程A
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                    initWithTarget:self
                                    selector:@selector(operation1)
                                    object:nil];
// 线程B
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc]
                                    initWithTarget:self
                                    selector:@selector(operation2)
                                    object:nil];

// 把线程A/B添加至队列
[queue addOperations:@[operation, operation2] waitUntilFinished:YES];

必须使用addOperations:方法把线程添加至队列,不然线程不会执行。或者,你也可以使用addOperation:方法添加单个线程。

2)NSBlockOperation

举个简单的使用列子介绍,都写了备注,就不再说明了:

// 创建线程任务
NSBlockOperation *blockOperation = [NSBlockOperation
                           blockOperationWithBlock:^{
                               NSLog(@"one - %@", [NSThread currentThread]);
                           }];;
// 添加新的操作
[blockOperation addExecutionBlock:^{
    NSLog(@"two - %@", [NSThread currentThread]);
}];

// 添加新的操作
[blockOperation addExecutionBlock:^{
    NSLog(@"three - %@", [NSThread currentThread]);
}];

// 执行线程任务
[blockOperation start];

3)NSOperationQueue

这里介绍一下NSOperation的依赖关系,依赖关系会影响线程执行的顺序:

// 创建操作队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

// 线程A
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"op1");
    [NSThread sleepForTimeInterval:2];
}];

// 线程B
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"op2");
}];

// 线程C
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"op3");
    [NSThread sleepForTimeInterval:2];
}];

// 线程B依赖线程C,也就是等线程C执行完之后才会执行线程B
[op2 addDependency:op3];
// 线程C依赖线程A,同上,只不过依赖对象改成了线程A
[op3 addDependency:op1];

// 为队列添加线程
[queue addOperation:op1];
[queue addOperation:op2];
[queue addOperation:op3];

注意:依赖关系可以多重依赖,但不要建立循环依赖。

在NSOperationQueue类中,我们可以使用cancelAllOperations方法取消所有的线程。这里需要说明一下,不是执行cancelAllOperations方法时就会马上取消,是等当前队列执行完,下面的队列不会再执行。

NSOperation方法及属性:

// 设置线程的最大并发数
@property NSInteger maxConcurrentOperationCount;

// 线程完成后调用的Block
@property (copy) void (^completionBlock)(void);

// 取消线程
- (void)cancel;

只列举上面那些,其它的方法就不全列出来了。

三、Grand Central Dispatch (GCD)

1)GCD的创建:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"线程 - %@", [NSThread currentThread]);
});

GCD也可以创建同步的线程,只需要把async改成sync即可。

2)重复执行线程:dispatch_apply

以下代码会执行4次:

dispatch_apply(4, DISPATCH_QUEUE_PRIORITY_DEFAULT, ^(size_t index) {
    // index则为执行的次数 0开始递增
    NSLog(@"one - %ld", index);
});

index参数为执行的次数,0开始递增

3)操作队列:dispatch_queue_create

// 创建队列
// 第一个参数是“字符串标识”,第二个参数是可选的,可以是NULL
dispatch_queue_t queue = dispatch_queue_create("com.garvey.post", NULL);

// 传入一个队列并执行队列(顺序执行)
dispatch_async(queue, ^{
    NSLog(@"aaa");
    [NSThread sleepForTimeInterval:2];
});
dispatch_async(queue, ^{
    NSLog(@"bbb");
    [NSThread sleepForTimeInterval:1];
});
dispatch_async(queue, ^{
    NSLog(@"ccc");
});

代码效果:以上会先执行aaa-》bbb-》ccc

4)GCD群组通知:dispatch_group_t

GCD的高级用法,等所有线程都完成工作后,再作通知。

// 创建群组
dispatch_group_t group = dispatch_group_create();

// 线程A
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"group1");
    [NSThread sleepForTimeInterval:2];
});

// 线程B
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"group2");
});

// 待群组里的线程都完成之后调用的通知
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"group success");
});

线程A和线程B都执行完之后,会调用通知打印group success。

5)GCD实现计时器

__block int time = 30;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0);
dispatch_source_set_event_handler(timer, ^{
    time--;
    NSLog(@"%d", time);
    if (time == 0) {
        dispatch_source_cancel(timer);
    }
});
dispatch_resume(timer);

代码效果:创建了一个计时器,计时器运行30秒,每过一秒会调用一次block,我们可以在block里面写代码。因为dispatch_source_t默认是挂起状态,因此我们使用时需要使用dispatch_resume方法先恢复,不然线程不会执行。

GCD方法及属性:

// 获取主线程
dispatch_get_main_queue()

// 创建队列:第一个参数是“字符串标识”,第二个参数是可选的,可以是NULL
dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);

// 创建异步调度队列
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);

// 恢复队列
void dispatch_resume(dispatch_object_t object);

// 暂停队列
void dispatch_suspend(dispatch_object_t object);

小结:本文主要介绍了IOS三种线程的线程使用方法,三种线程各有好处。苹果是推荐我们使用GCD,因为GCD是这三种里面最轻量级的,也是消耗资源最低的,并且它执行效率比其它两种都高。不过,还是看个人使用及开发需求去定义比较好。

题外话:这篇博文是我注册以来发布最长的一篇技术随笔,也是消耗最多精力的随笔,喜欢的朋友希望能给个赞,谢谢。

本文参考:

iOS多线程开发

GCD的另一个用处是可以让程序在后台较长久的运行。

全面掌握iOS多线程攻略 —— PS:这个攻略较多,但是有很多重复的内容。



博文作者:GarveyCalvin

博文出处:http://www.cnblogs.com/GarveyCalvin/

本文版权归作者和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作!

时间: 2024-10-07 05:59:55

IOS开发-多线程编程技术(Thread、Cocoa operations、GCD)的相关文章

IOS开发——多线程编程

1."省电,流畅,优质应用,响应速度快,用户体验好--"也许是众多用户眼中的苹果系统. 2.在众手机商拼CPU主频,拼4核,8核的年代,苹果依然坚持双核,iphone用户体验仍然坚挺. 以上两点IOS是如何优化,在续航,流畅度和响应速度上完胜安卓,答案就是多线程&RunLoop... RunLoop是IOS事件响应与任务处理最核心机制,它贯穿IOS整个系统运作. RunLoop不像一般的线程循环等待任务,传统的线程循环等待任务会导致CPU时间被占用,虽然你设置了睡眠时间,但很多

IOS开发 多线程编程 - NSThread

每个iOS应用程序都有个专门用来更新显示UI界面.处理用户的触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来极坏的用户体验.一般的解决方案就是将那些耗时的操作放到另外一个线程中去执行,多线程编程是防止主线程堵塞,增加运行效率的最佳方法 iOS支持多个层次的多线程编程,层次越高的抽象程度越高,使用也越方便,也是苹果最推荐使用的方法.下面根据抽象层次从低到高依次列出iOS所支持的多线程编程方法: 1.Thread :是三种方法里面相对轻量级的,

iOS开发——多线程编程(GCD)

Grand Central Dispatch简介 Grand Central Dispatch 简称 GCD 是苹果公司开发的技术,是对于多核编程的较新解决方案.它主要用于优化应用程序以支持多核处理器以及其他对称多处理系统. GCD 提供了一种很简单的操作方式来实现并行处理.你可以把你要的并发执行的代码放在一个block钟,然后把这个block加入到一个queue当中. 在GCD中为我们需要执行的block提供了3种队列: Main:这个队列顺序执行我们的block,并保证这些block都在主线

iOS开发多线程编程2 - NSOperation

1.简介 NSOperation实例封装了需要执行的操作和执行操作所需的数据,并且能够以并发或非并发的方式执行这个操作. NSOperation本身是抽象基类,因此必须使用它的子类,使用NSOperation子类的方式有2种: 1> Foundation框架提供了两个具体子类直接供我们使用:NSInvocationOperation和NSBlockOperation 2> 自定义子类继承NSOperation,实现内部相应的方法 2.执行操作 NSOperation调用start方法即可开始执

iOS开发 多线程-转自MJ的GCD详解

一.简介 在iOS所有实现多线程的方案中,GCD应该是最有魅力的,因为GCD本身是苹果公司为多核的并行运算提出的解决方案.GCD在工作时会自动利用更多的处理器核心,以充分利用更强大的机器.GCD是Grand Central Dispatch的简称,它是基于C语言的.如果使用GCD,完全由系统管理线程,我们不需要编写线程代码.只需定义想要执行的任务,然后添加到适当的调度队列(dispatch queue).GCD会负责创建线程和调度你的任务,系统直接提供线程管理 二.调度队列(dispath qu

【转】iOS多线程编程技术之NSThread、Cocoa NSOperation、GCD

转自容芳志的博客 简介 iOS有三种多线程编程的技术,分别是: (一)NSThread (二)Cocoa NSOperation (三)GCD(全称:Grand Central Dispatch) 这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的. 三种方式的优缺点介绍: 1)NSThread: 优点:NSThread 比其他两个轻量级 缺点:需要自己管理线程的生命周期,线程同步.线程同步对数据的加锁会有一定的系统开销 NSThread实现的技术

iOS多线程编程技术之NSThread、Cocoa NSOperation、GCD

简介iOS有三种多线程编程的技术,分别是:(一)NSThread(二)Cocoa NSOperation(三)GCD(全称:Grand Central Dispatch) 这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的. 三种方式的优缺点介绍:1)NSThread:优点:NSThread 比其他两个轻量级缺点:需要自己管理线程的生命周期,线程同步.线程同步对数据的加锁会有一定的系统开销 NSThread实现的技术有下面三种:一般使用cocoa

iOS开发——多线程OC篇&多线程详解

多线程详解 前面介绍了多线程的各种方式及其使用,这里补一点关于多线程的概念及相关技巧与使用,相信前面不懂的地方看了这里之后你就对多线程基本上没有什么问题了! 1——首先ios开发多线程中必须了解的概念: 进程 正在进行中的程序被称为进程,负责程序运行的内存分配 每一个进程都有自己独立的虚拟内存空间 线程 线程是进程中一个独立的执行路径(控制单元) 一个进程中至少包含一条线程,即主线程 可以将耗时的执行路径(如:网络请求)放在其他线程中执行 创建线程的目的就是为了开启一条新的执行路径,运行指定的代

iOS开发多线程基础知识 NSOperation

-------NSOperation简介---- 1.NSOperation的作用 ·配合使用NSOperation和NSOperationQueue也能实现多线程编程 2.NSOperation和NSOperationQueue实现多线程的具体步骤 ·先将需要执行的操作封装到一个NSOperation对象中 ·然后将NSOperation对象添加到NSOperationQueue中 ·系统会自动将NSOperation中封装的操作放到一条新线程中执行 ---------NSOperation的