ios的多线程,同步异步操做,都是咱们平常的开发中常常会遇到的问题,本文把常见的ios线程,同步异步的操做进行了整理。
我博客中大部分示例代码都上传到了github,地址是:https://github.com/coolnameismy/demo,点击跳转代码下载地址java
本文代码存放目录是 ThreadAndAsynchronizationios
若是你们支持,请follow个人github帐号,并fork个人项目,有其余问题能够在github上给我留言或者给我发邮件,coolnameismy@hotmail.com,blog的RSS订阅地址:http://liuyanwei.jumppo.com/pages/rss.xmlgit
线程和进程:网上有一大堆很专业的说法,大多数说的都比较复杂,越复杂的解释其实说的越准确和严谨,可是经常会把人弄糊涂。这里我也不去解释了,大多数场景你能够理解为,一个应用程序就是一个进程,而一个进程能够分为多个线程github
多线程:大多数框架都支持一个进程启多个线程,好比 c#、java、obejctive-c,可是并非全部的框架都支持,好比flex的框架就不支持多线程。 多线程必需要有多核的cpu支持才行,对应单核cpu,不管你起多少个线程,都是在同一个cpu上跑程序,速度并不会有任何变化。对于多核cpu,多个线程会在多个cpu中同时运行,从而加快程序的执行速度。c#
多线程适用场景 最多见的是网络下载,在网络下载的适合,你总不能让程序一直无响应吧,因此你启动另外一个线程去下载,留着主线程去相应用户的ui事件。多线程适合一些高io,低cpu的操做。安全
同步就是顺序往下执行。举例:烧完水后泡茶网络
异步就是几件事情同时在执行。烧水的时候拿出茶具,洗茶具,而后泡茶。其中烧水和拿茶具,洗茶具是同时进行的。多线程
并行和串行 并行就是几我的同时作一件事,串行就是一我的同时作几件事。框架
同步是咱们通常程序顺序执行,异步是大多数时候是多线程,可是却不必定。好比方法回叫和定时执行的方法也是异步操做,单不必定全是多线程。异步
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"); }
/* *使用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"); }
/* *使用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"); }
/* *使反面教材,他不是多线程,但能够执行异步操做。最经常使用的就是定时执行一个任务,重复或非重复。 */ -(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"); }
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"); }