iOS多线程总结
来源:互联网 发布:保险公司首席数据官 编辑:程序博客网 时间:2024/05/16 09:01
今天没什么事做就对iOS的多线程做一次总结,纯属个人看法,初学者可以参考下。对于多线程我想无论是面试还是实际开发大家都不会陌生;
严格意义来讲iOS多线程算是4种:
- PThreads
- NSThread
- GCD
- NSOPeration/NSOperationQueue;
PThreads
这个是基于C语音定义的POSIX Threads(简称PThreads)标准线程,但是对于iOS开发者使用率很低,原因是有二:
- 调用的都是C函数和语法,对于习惯OC或者Swift开发的我们来说,很蛋疼;
- 线程的生命周期需要我们手动管理。
这个一般用在实现操作系统和PHP里(Unix、Linux、Mac OS X等)
- (void)Pthreads { pthread_t thread; //创建一个线程并执行 start是一个函数指针 pthread_create(&thread, NULL, start, NULL);}void *start(void *data) { //这里执行线程操作 NSLog(@"%@",[NSThread currentThread]); return NULL;}有兴趣的同学可以看看。
NSThread
这个是苹果自己开发,NSThread是轻量级多线程生命周期需要手动管理因为扩展性不高,有很多局限性只能偶尔用用 。
上代码:
- (void)NSThread { //先创建后执行 NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadRun) object:nil]; [thread start]; //创建并执行 [NSThread detachNewThreadSelector:@selector(threadRun) toTarget:self withObject:nil]; //perform里唯一一个多线程方法 如果线程方法要刷新UI可以使用 //- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait; [self performSelectorInBackground:@selector(threadRun) withObject:nil];}- (void)threadRun { NSLog(@"threadRun:%@",[NSThread currentThread]);}
GCD
下面是重点,Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。GCD能充分利用手机性能,让运行效率更快,也是苹果主推的多线程开发方式。
在GCD中,有两个概念很重要就是任务和队列,任务分同步执行和异步执行两种方式,队列也分串行队列和并行队列,下面我们来看它们的创建和使用:
//1.初始化/获取系统队列 //获取主队列 ()一般只负责刷新UI,耗时任务都交给其他线程 dispatch_queue_t queue = dispatch_get_main_queue(); //创建自己的队列 //串行队列 dispatch_queue_t queue1 = dispatch_queue_create("队列标识符", nil); dispatch_queue_t queue2 = dispatch_queue_create("队列标识符", DISPATCH_QUEUE_SERIAL); //并行队列 dispatch_queue_t queue3 = dispatch_queue_create("队列标识符", DISPATCH_QUEUE_CONCURRENT); //获取全局并行队列 只要是并行任务一般都加入到这个队列。这是系统提供的一个并发队列。 dispatch_queue_t queue4 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //2.任务的创建和执行方法(同步和异步) //同步任务 dispatch_sync(queue3, ^{ NSLog(@"GCD-同步%@",[NSThread currentThread]); sleep(5); NSLog(@"GCD-同步—后%@",[NSThread currentThread]); }); //异步任务 dispatch_async(queue3, ^{ NSLog(@"GCD-异步%@",[NSThread currentThread]); });
从上面的代码可以看出队列还主队列(系统队列)还有自定义队列(多线程),自定义队列创建的时候两个参数第一个是标识符可以为空;第二个为空或者DISPATCH_QUEUE_SERIAL为串行队列,DISPATCH_QUEUE_CONCURRENT为并行队列。还有一个全局并行队列一般的并发任务都会加入这个队列,其实无论是并行队列还是串行队列都是以先进先出原则,区别在于并行队列是取一个开一个线程执行,在取下一个,中间取的时间很快;串行队列是取出一个执行完成以后再取出下一个,一个一个的执行。需要注意的是GCD会根据系统资源限制并行数量。
//3.队列组 队列组可以将很多队列添加到一个组里,这样做的好处是,当这个组里所有的任务都执行完了,队列组会通过一个方法通知我们。 //3.1创建队列组 dispatch_group_t group = dispatch_group_create(); //3.2创建队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //3.3多次使用队列组的方法执行任务,只有异步方法 //执行3此循环 dispatch_group_async(group, queue, ^{ for (int i = 0; i < 3; i++) { NSLog(@"group-01:%@",[NSThread currentThread]); } }); //主队列执行8此循环 dispatch_group_async(group, dispatch_get_main_queue(), ^{ for (int i = 0; i < 8; i++) { NSLog(@"group-02:%@",[NSThread currentThread]); } }); //执行5次循环 dispatch_group_async(group, queue, ^{ for (int i = 0; i < 5; i++) { NSLog(@"group-03:%@",[NSThread currentThread]); } }); dispatch_group_notify(group, dispatch_get_main_queue(), ^{ NSLog(@"完成-04:%@",[NSThread currentThread]); });
NSOperation/NSOperationQueue
NSOperation 是苹果公司对 GCD的封装,完全面向对象,所以使用起来更好理解。大家可以看到 NSOperation和 NSOperationQueue分别对应 GCD的任务和队列
NSOperation只是一个抽象类,所以不能封装任务。但它有 2个子类用于封装任务。
分别是:NSInvocationOperation和 NSBlockOperation。
创建一个 Operation后,需要调用 start方法来启动任务,它会默认在当前队列同步执行。
当然你也可以在中途取消一个任务,只需要调用其 cancel方法即可
//1.创建 //NSInvocationOperation NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(threadRun) object:nil]; //开始执行 [operation start]; //NSBlockOperation NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation:%@",[NSThread currentThread]); }]; /* NSBlockOperation 还有一个方法:addExecutionBlock: ,通过这个方法可以给 Operation 添加多个执行 Block。这样 Operation 中的任务会并发执行,它会在主线程和其它的多个线程 执行这些任务 */ for (int i = 0; i < 5; i++) { [blockOperation addExecutionBlock:^{ NSLog(@"blockOperation-第%d次:%@",i,[NSThread currentThread]); }]; } [blockOperation start]; /* 看过上面的内容就知道,我们可以调用一个 NSOperation 对象的 start() 方法来启动这个任务,但是这样做他们默认是 同步执行 的。就算是 addExecutionBlock 方法,也会在 当前线程和其他线程 中执行,也就是说还是会占用当前线程。这是就要用到队列 NSOperationQueue 了。而且,按类型来说的话一共有两种类型:主队列、其他队列。只要添加到队列,会自动调用任务的 start() 方法 */ //NSOperationQueue 获取主队列(串行) NSOperationQueue *queue = [NSOperationQueue mainQueue]; //创建其他队列 NSOperationQueue *queue1 = [[NSOperationQueue alloc] init]; NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"%@",[NSThread currentThread]); }]; //这里可以添加多个operation [queue1 addOperation:operation1];
NSOperation 有一个非常实用的功能,那就是添加依赖。比如有 3个任务:A:从服务器上下载一张图片,B:给这张图片加个水印,C:把图片返回给服务器。这时就可以用到依赖了:
//1.任务一:下载图片 NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下载图片:%@",[NSThread currentThread]); }]; //2.任务二:打水印 NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"打水印:%@",[NSThread currentThread]); }]; //3.任务三:上传图片 NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"上传图片:%@",[NSThread currentThread]); }]; //4.设置依赖 注意:不能添加相互依赖,会死锁,比如 A依赖B,B依赖A。 [operation2 addDependency:operation1]; //任务二依赖任务一 [operation3 addDependency:operation2]; //任务三依赖任务二 //5.创建队列并加入 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [queue addOperations:[NSArray arrayWithObjects:operation1,operation2,operation3, nil] waitUntilFinished:NO];以上只是一些基本使用方法,想了解更多可以去网上找或者去看官方文档;
使用多线程我们就需要考虑数据同步的问题
其他
互斥锁:给需要同步的代码块加一个互斥锁,就可以保证每次只有一个线程访问此代码块。
@synchronized(self) { //需要执行的代码块 }我们也可以在队列的结尾加一个串行队列,来达到数据同步的效果方法有很多。
0 0
- IOS多线程,同步总结
- IOS多线程,同步总结
- iOS多线程总结
- IOS多线程总结
- iOS多线程初步总结
- iOS 中的多线程总结
- iOS多线程个人总结
- iOS多线程总结
- iOS 多线程总结
- iOS多线程知识总结
- iOS多线程总结
- iOS 多线程总结
- iOS-多线程总结
- iOS多线程编程总结
- iOS多线程知识总结
- iOS多线程比较、总结
- iOS多线程总结
- iOS基础:多线程总结
- 欢迎使用CSDN-markdown编辑器
- 树莓派h264实时视频监控
- 数据中显示"刚刚、几天前、几天前、几个月"等个人的想法
- android - 下拉刷新 & 强制刷新notifyDataSetChanged
- PCL RANSAC代码阅读
- iOS多线程总结
- Java中的ThreadLocal深入理解
- 时间管理的三部曲
- iOS开发:网络参考模型
- 在UNIX中关于RM 命令的警示
- lucene5.5根据现有分词器改造做同义词分词器
- 虚拟机+ubuntu 图形界面和终端界面的切换
- 函数调用的区别:_cdecl以及_stdcall
- vfork程序无限循环