文档章节

ios的线程和同步异步操作

lewis-180
 lewis-180
发布于 2015/12/08 16:54
字数 2115
阅读 61
收藏 1

ios的线程和同步异步操作

ios的线程和同步异步操作

ios的多线程,同步异步操作,都是我们日常的开发中经常会遇到的问题,本文把常见的ios线程,同步异步的操作进行了整理。

代码下载:

我博客中大部分示例代码都上传到了github,地址是:https://github.com/coolnameismy/demo,点击跳转代码下载地址

本文代码存放目录是 ThreadAndAsynchronization

如果大家支持,请follow我的github账号,并fork我的项目,有其他问题可以在github上给我留言或者给我发邮件,coolnameismy@hotmail.com,blog的RSS订阅地址:http://liuyanwei.jumppo.com/pages/rss.xml

基础知识


1.线程和进程 ,多线程

线程和进程:网上有一大堆很专业的说法,大多数说的都比较复杂,越复杂的解释其实说的越准确和严谨,但是常常会把人弄糊涂。这里我也不去解释了,大多数场景你可以理解为,一个应用程序就是一个进程,而一个进程可以分为多个线程

多线程:大多数框架都支持一个进程启多个线程,比如 c#、java、obejctive-c,但是并不是所有的框架都支持,比如flex的框架就不支持多线程。 多线程必须要有多核的cpu支持才行,对应单核cpu,无论你起多少个线程,都是在同一个cpu上跑程序,速度并不会有任何变化。对于多核cpu,多个线程会在多个cpu中同时运行,从而加快程序的执行速度。

多线程适用场景 最常见的是网络下载,在网络下载的适合,你总不能让程序一直无响应吧,所以你启动另一个线程去下载,留着主线程去相应用户的ui事件。多线程适合一些高io,低cpu的操作。

2.同步和异步,并行和串行

同步就是顺序往下执行。举例:烧完水后泡茶

异步就是几件事情同时在执行。烧水的时候拿出茶具,洗茶具,然后泡茶。其中烧水和拿茶具,洗茶具是同时进行的。

并行和串行 并行就是几个人同时做一件事,串行就是一个人同时做几件事。

3.同步异步操作和多线程的联系和区别

同步是我们一般程序顺序执行,异步是大多数时候是多线程,但是却不一定。比如方法回叫和定时执行的方法也是异步操作,单不一定全是多线程。

4.ios中的同步异步方法和多线程技术

1 performSelector

支持多线程和异步操作,使用简单,但是没有没有线程的一些控制和调度的操作

2 NSThread

支持多线程和异步操作,使用简单,比performSelector稍微复杂一些,performSelector背后使用的就是NSThread,但是没有没有线程的一些控制和调度的操作

3 NSTimer

不支持多线程操作,但是可以执行异步操作,异步操作很方便,最常用的就是定时执行和延迟执行某一方法

4 GCD

支持多线程,同步异步操作,线程控制,线程队列,线程信号等等,IOS和OS中最强大的线程管理都是是它了。 要说缺点的话,就是代码比较复杂,前面能实现的就用前面的把,如果实现不了,那找它准没错。

代码例子


代码注释写的很全,大家直接看注释都能懂,可以在github上把代码下载下来跑跑看。

//ios多线程,同步异步的使用,大家可以切换类,去掉注释跑跑看 - (void)viewDidLoad {     [super viewDidLoad];     //使用performSelector的多线程和异步     //[self performSelectorFunction];     //使用NSThread的多线程     //[self NSThreadFunction];     //使用NSTimer的反面教材     //[self NSTimerFunction];     //使用GCD的多线程     //[self GCDFunction]; } //耗时2秒的方法 -(void)function1{     [NSThread sleepForTimeInterval:2];     NSLog(@"function1 done"); }

1. performSelector的使用

/*  *使用performSelector 的多线程  *优点:简单  *缺点:没有串行并线队列,不能实现高级线程调度  */ -(void)performSelectorFunction{     NSLog(@"performSelectorFunction start");     //同步     //方式执行,直接执行function1     //[self performSelector:@selector(function1)];     //异步,线程阻塞     //延迟两秒执行function1,在function1执行期间,主线程是阻塞的,表现就是界面无响应。     //[self performSelector:@selector(function1) withObject:nil afterDelay:2];     //线程阻塞 最后一个参决定是同步还是异步     // 主线程上执行,主线程阻塞,waitUntilDone:YES:等待执行完成顺序执行,waitUntilDone:NO 先执行后面语句     //[self performSelectorOnMainThread:@selector(function1) withObject:nil waitUntilDone:NO];     //异步,非阻塞     //子线程上执行     [self performSelectorInBackground:@selector(function1) withObject:nil];     NSLog(@"performSelectorFunction end"); }

2. NSThreadFunction的使用

/*  *使用NSThread 的多线程  *优点:简单  *缺点:没有串行并线队列,不能实现高级线程调度,和performSelector是一样的。  */ -(void)NSThreadFunction{     NSLog(@"NSThreadFunction start");     //同步 阻塞     //线程暂停 2秒     //[NSThread sleepForTimeInterval:2];     //异步 非阻塞     //显示创建的方式执行     //NSThread *myThread = [[NSThread alloc]initWithTarget:self selector:@selector(function1) object:nil];     //[myThread start];     //异步 非阻塞     //静态方法执行线程     //[NSThread detachNewThreadSelector:@selector(function1) toTarget:self withObject:nil];     NSLog(@"NSThreadFunction end"); }

3. NSTimerFunction的使用

/*  *使反面教材,他不是多线程,但可以执行异步操作。最常用的就是定时执行一个任务,重复或非重复。  */ -(void)NSTimerFunction{     NSLog(@"NSTimerFunction start");     //定时执行任务,可以重复和不重复     //NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(function1) userInfo:nil repeats:NO];     //暂时停止定时器     //[timer setFireDate:[NSDate distantFuture]];     //重新开启定时器     //[timer setFireDate:[NSDate distantPast]];     //永久通知定时器     //[timer invalidate];     //timer = nil;     NSLog(@"NSTimerFunction end"); }

4. GCD的使用

GCD的方法很多,用法也很多,这里只列举一些常用的方法。常用的方法包括:

  • 同步、非阻塞执行

  • 异步非阻塞执行

  • 一次性执行

  • 延迟执行

  • 线程队列串行执行

  • 线程队列控制(屏障,同步等待,线程暂停和恢复,线程信号量控制等)

/*  *使用GCD 的多线程  *优点:有很多串行并线队列多线程,block实现线程方法,高级,好用,方法多。  *缺点:在很多不需要高级控制线程的场景可以不用使用GCD  */ -(void)GCDFunction{     NSLog(@"GCDFunction start");     //获取一个队列     dispatch_queue_t defaultQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);     //dispatch_async:异步方式执行方法(最常用)     //    dispatch_async(defaultQueue, ^{     //        [self function1];     //    });     //dispatch_sync:同步方式使用场景,比较少用,一般与异步方式进行调用     //    dispatch_async(defaultQueue, ^{     //       NSMutableArray *array = [self GCD_sync_Function];     //       dispatch_async(dispatch_get_main_queue(), ^{     //           //利用获取的arry在主线程中更新UI     //     //       });     //    });     //dispatch_once:一次性执行,常常用户单例模式.这种单例模式更安全     //    static dispatch_once_t onceToken;     //    dispatch_once(&onceToken, ^{     //        // code to be executed once     //        NSLog(@"dispatch_once");     //    });     //dispatch_after 延迟异步执行     //    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 2.0 * NSEC_PER_SEC);     //    dispatch_after(popTime, defaultQueue, ^{     //        NSLog(@"dispatch_after");     //    });     //dispatch_group_async 组线程可以实现线程之间的串联和并联操作     //    dispatch_group_t group = dispatch_group_create();     //    NSDate *now = [NSDate date];     //    //做第一件事 2秒     //    dispatch_group_async(group, defaultQueue, ^{     //        [NSThread sleepForTimeInterval:2];     //         NSLog(@"work 1 done");     //    });     //    //做第二件事 5秒     //    dispatch_group_async(group, defaultQueue, ^{     //        [NSThread sleepForTimeInterval:5];     //        NSLog(@"work 2 done");     //    });     //     //    //两件事都完成后会进入方法进行通知     //    dispatch_group_notify(group, defaultQueue, ^{     //        NSLog(@"dispatch_group_notify");     //        NSLog(@"%f",[[NSDate date]timeIntervalSinceDate:now]);//总共用时5秒,因为2个线程同时进行     //    });     //dispatch_barrier_async :作用是在并行队列中,等待前面的队列执行完成后在继续往下执行     //    dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);     //    dispatch_async(concurrentQueue, ^{     //        [NSThread sleepForTimeInterval:2];     //        NSLog(@"work 1 done");     //    });     //    dispatch_async(concurrentQueue, ^{     //        [NSThread sleepForTimeInterval:2];     //        NSLog(@"work 2 done");     //    });     //    //等待前面的线程完成后执行     //    dispatch_barrier_async(concurrentQueue, ^{     //         NSLog(@"dispatch_barrier_async");     //    });     //     //    dispatch_async(concurrentQueue, ^{     //        [NSThread sleepForTimeInterval:3];     //        NSLog(@"work 3 done");     //    });     //dispatch_semaphore 信号量的使用,串行异步操作     //    dispatch_semaphore_create   创建一个semaphore     //   dispatch_semaphore_signal   发送一个信号     //   dispatch_semaphore_wait    等待信号     /*应用场景1:马路有2股道,3辆车通过 ,每辆车通过需要2秒      *条件分解:         马路有2股道 <=>  dispatch_semaphore_create(2) //创建两个信号         三楼车通过 <=> dispatch_async(defaultQueue, ^{ } 执行三次         车通过需要2秒 <=>  [NSThread sleepForTimeInterval:2];//线程暂停两秒      */     dispatch_semaphore_t semaphore = dispatch_semaphore_create(2);         dispatch_async(defaultQueue, ^{             dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);             [NSThread sleepForTimeInterval:2];             NSLog(@"carA pass the road");             dispatch_semaphore_signal(semaphore);         });         dispatch_async(defaultQueue, ^{             dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);             [NSThread sleepForTimeInterval:2];             NSLog(@"carB pass the road");             dispatch_semaphore_signal(semaphore);         });         dispatch_async(defaultQueue, ^{             dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);             [NSThread sleepForTimeInterval:2];             NSLog(@"carC pass the road");             dispatch_semaphore_signal(semaphore);         });     //应用场景2 :原子性保护,保证同时只有一个线程进入操作     //    dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);     //    for(int i=0 ;i< 10000 ;i++){     //        dispatch_async(defaultQueue, ^{     //            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);     //            NSLog(@"i:%d",i);     //            dispatch_semaphore_signal(semaphore);     //        });     //    }     NSLog(@"GCDFunction end"); }

© 著作权归作者所有

lewis-180
粉丝 5
博文 40
码字总数 67621
作品 0
南宁
私信 提问
关于iOS多线程,这边勉强可以看看(OC&Swift)

iOS开发多线程总是绕不过的坎,看了很多前辈们优秀的文章,如:关于iOS多线程,我说,你听,没准你就懂了!、谈iOS多线程(NSThread、NSOperation、GCD)编程、iOS多线程:『GCD』详尽总结、i...

Andy_Ron
2018/08/26
0
0
2018 iOS 面试题大全(补充完整版)

原文地址:2018 iOS 面试题大全 由于原作者并没有继续更新,这里我转过来继续更新下 这个栏目将持续更新--请iOS的小伙伴关注! 1、iOS 应用导航模式有哪些? 2、iOS 中持久化方式有哪些? 3、...

Theendisthebegi
2018/11/15
0
0
dispatch_sync和dispatch_async的区别

dispatchsync 线程同步、dispatchasync线程异步 //同步 这些代码输出的结果是 1 2 3 4 依次输出、无论你运行多少次都会是这一种结果 但是来看下面的异步呢? //并行队列、同步 输出的结果是 ...

久依
01/10
0
0
IOS NSNotification 通知

一. 先看下官方对NSNotification通知的解释 1. NSNotification 通知  @interface NSNotification : NSObject   接口通知,继承NSObject,实现NSCopying,NSCoding协议  A container for...

冬季的暖风
2018/08/02
0
0
cordova与ios native code交互的原理

很早以前写了一篇博客,总结cordova插件怎么调用到原生代码: cordova调用过程,不过写得太水,基本没有提到原理。最近加深了一点理解,重新补充说明一下 js调用native 下面是我们产品中的代...

Michaelyn
2017/10/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

2019年普通高校在川招生专业及名额介绍文科 带学费

2019年普通高校在川招生专业及名额介绍文科 带学费

asdtiang
15分钟前
1
0
springCloud配置中心config配置svn(踩坑记录)(基于consul)

新建一个config Server模块; 引入如下依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId></dependency>......

为何不可1995
15分钟前
0
0
mysql相关tips(持续更新)

1.字符集:utf8mb4 mysql 5.5.3之后出来的字符集,占用1-4个字节,最大占用的字节数为4.目前这个字段主要应用在(Emoji表情)。utf8mb4兼容utf8(1-3个字节),且比utf8能表示更多的字符。什...

lara_
15分钟前
0
0
微服务开源生态报告 No.1

从关注开源,到使用开源,再到参与开源贡献,越来越多的国内开发者通过开源技术来构建业务。 截止目前,Arthas / Dubbo / ChaosBalde / Nacos / RocketMQ / Seata / Sentinel / Spring Clou...

阿里云官方博客
18分钟前
1
0
MaxCompute 费用暴涨之存储压缩率降低导致SQL输入量变大

现象:同样的SQL,每天处理的数据行数差不多,但是费用突然暴涨甚至会翻数倍。 分析: 我们先明确MaxCompute SQL后付费的计费公式:一条SQL执行的费用=扫描输入量 ️ SQL复杂度 ️ 0.3(¥/GB...

zhaowei121
20分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部