假如有3个任务如下
- (int)mission1 { [NSThread sleepForTimeInterval:1]; //模拟耗时操作 return 1; } - (int)mission2 { [NSThread sleepForTimeInterval:2]; //模拟耗时操作 return 2; } - (int)mission3 { [NSThread sleepForTimeInterval:3]; //模拟耗时操作 return 3; }
1.普通的执行方法,消耗时间为6秒
NSDate* startTime = [NSDate date]; int ans1 = [self mission1]; int ans2 = [self mission2]; int ans3 = [self mission3]; self.textView.text = [NSString stringWithFormat:@"%i %i %i", ans1, ans2, ans3]; NSDate* endTime = [NSDate date]; NSLog(@"%f", [endTime timeIntervalSinceDate:startTime]);
注意:
由于是顺序执行,所以共消耗6秒
2.任务完全在后台的线程中运行,消耗时间为6秒
NSDate* startTime = [NSDate date]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ int ans1 = [self mission1]; int ans2 = [self mission2]; int ans3 = [self mission3]; //必须在主线程中更新UI dispatch_async(dispatch_get_main_queue(), ^{ self.textView.text = [NSString stringWithFormat:@"%i %i %i", ans1, ans2, ans3]; }); NSDate* endTime = [NSDate date]; NSLog(@"%f", [endTime timeIntervalSinceDate:startTime]); });
注意:
(1)dispatch_get_global_queue的作用是获得一个已经存在并始终可用的全局队列,第一个参数是队列优先级,第二个目前默认为0
(2)dispatch_async的作用是队列获取程序块,并将程序块传递给一个后台线程,这里是顺序执行,所以消耗时间也是6秒
(3)当程序块被执行完之后,整个方法可能已经退出,此时程序块外的变量startTime理应被销毁,程序块如何正确去访问startTime变量呢?其实程序块被创建的时候,会执行[startTime retain],并将返回值赋值给程序块内部的一个同名(startTime)变量
(4)所有的UI更新都应该在主线程中完成,所以必须将self.textView.text = [NSString stringWithFormat:@"%i %i %i", ans1, ans2, ans3];扔到主线程中执行,dispatch_get_main_queue的作用是获得存在于主线程上的特殊队列
3.任务在并发的线程中执行,消耗时间为3秒
NSDate* startTime = [NSDate date]; dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ __block int ans1, ans2, ans3; dispatch_group_t group = dispatch_group_create(); //创建一个dispatch group dispatch_group_async(group, queue, ^{ans1 = [self mission1];}); dispatch_group_async(group, queue, ^{ans2 = [self mission2];}); dispatch_group_async(group, queue, ^{ans3 = [self mission3];}); dispatch_group_notify(group, queue, ^{ //必须在主线程中更新UI dispatch_async(dispatch_get_main_queue(), ^{ self.textView.text = [NSString stringWithFormat:@"%i %i %i", ans1, ans2, ans3]; }); NSDate* endTime = [NSDate date]; NSLog(@"%f", [endTime timeIntervalSinceDate:startTime]); }); });
注意:
(1)使用分配组dispatch_group将多个任务分配给多个线程来同时执行,当该组的所有线程完成的时候,会执行dispatch_group_notify中的程序块。
(2)由于线程是并发进行所以消耗时间为3秒
(3)ans1,ans2和ans3是在程序块中赋值,为了能够在之后使用这些变量,需要使用__block修饰。如果不用__block修饰,当ans1在程序块中被修改之后,在程序块之外ans1并不会被修改,因为程序块只是做了简单的retain操作和值的复制。