- (void)viewDidLoad {
[super viewDidLoad];
[self firstTest];
}
-(void)viewWillAppear:(BOOL)animated{
[self secondTest];
}
-(void)viewDidAppear:(BOOL)animated{
[self thirdTest];
}
- (void)firstTest {
NSLog(@"=================1");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"=================2");
});
NSLog(@"=================3");
}
- (void)secondTest {
NSLog(@"ViewWillAppear=============");
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"=================4");
dispatch_sync(dispatch_get_main_queue(), ^{
[NSThread sleepForTimeInterval:5.0f];
NSLog(@"=================5");
});
NSLog(@"=================6");
});
NSLog(@"==========Main Thread Blocked");
}
- (void)thirdTest {
NSLog(@"ViewDidAppear=============");
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"=================7");
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(@"=================8");
});
NSLog(@"=================9");
});
}
最佳答案
每个dispatch_async(dispatch_get_global_queue(...))
都可能在由全局队列管理的工作线程上运行,因此您可能会看到三个线程,但也有可能在第二个线程启动之前完成对全局队列的第一个分派,因此您可能最终会使用两个线程,但如果您在secondTest
中同步分派,则几乎可以肯定用三根线。
因此主线程将运行1、3、2、5和8,secondTest
中全局队列调用的工作线程将运行4和6,thirdTest
中的工作线程将运行7和9。
值得一提的是,xcode 8更新的活动跟踪使这类分析变得更加简单。例如,我可以用NSLog
语句替换kdebug_signpost
语句:
#import <sys/kdebug_signpost.h>
@interface ViewController ()
@property (nonatomic, strong) dispatch_group_t group;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
kdebug_signpost_start(1, 0, 0, 0, 1);
// create a group that will call notify block when three `dispatch_group_leave` calls happen
// by having an alert show up when all three tests are done, I can terminate the instruments
// session at the appropriate time
self.group = dispatch_group_create();
dispatch_group_enter(self.group);
dispatch_group_enter(self.group);
dispatch_group_enter(self.group);
dispatch_group_notify(self.group, dispatch_get_main_queue(), ^{
UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil message:@"Done" preferredStyle:(UIAlertControllerStyleAlert)];
[controller addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:controller animated:true completion:nil];
});
// now carry on doing the tests
[self firstTest];
kdebug_signpost_end(1, 0, 0, 0, 1);
}
-(void)viewWillAppear:(BOOL)animated{
kdebug_signpost_start(2, 0, 0, 0, 2);
[super viewWillAppear:animated];
[self secondTest];
kdebug_signpost_end(2, 0, 0, 0, 2);
}
-(void)viewDidAppear:(BOOL)animated{
kdebug_signpost_start(3, 0, 0, 0, 3);
[super viewDidAppear: animated];
[self thirdTest];
kdebug_signpost_end(3, 0, 0, 0, 3);
}
- (void)firstTest {
dispatch_async(dispatch_get_main_queue(), ^{
kdebug_signpost_start(4, 0, 0, 0, 1);
[NSThread sleepForTimeInterval:1];
kdebug_signpost_end(4, 0, 0, 0, 1);
dispatch_group_leave(self.group);
});
}
- (void)secondTest {
dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0);
dispatch_async(queue, ^{
kdebug_signpost_start(5, 0, 0, 0, 2);
dispatch_sync(dispatch_get_main_queue(), ^{
kdebug_signpost_start(6, 0, 0, 0, 2);
[NSThread sleepForTimeInterval:5.0f];
kdebug_signpost_end(6, 0, 0, 0, 2);
dispatch_group_leave(self.group);
});
kdebug_signpost_end(5, 0, 0, 0, 2);
});
}
- (void)thirdTest {
dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0);
dispatch_async(queue, ^{
kdebug_signpost_start(7, 0, 0, 0, 3);
dispatch_sync(dispatch_get_main_queue(), ^{
kdebug_signpost_start(8, 0, 0, 0, 3);
[NSThread sleepForTimeInterval:1.0f];
kdebug_signpost_end(8, 0, 0, 0, 3);
dispatch_group_leave(self.group);
});
kdebug_signpost_end(7, 0, 0, 0, 3);
});
}
@end
我使用第一个参数来表示我感兴趣的跟踪任务,使用第四个参数来表示“系统跟踪”中的颜色。然后,我可以指定与System Trace in Depth中概述的这些唯一标识符相关联的名称,以便它们在“兴趣点”部分显示为“区域”。然后你可以在仪器中使用“系统跟踪”工具,你可以看到发生了什么。这些命名区域和它们关联的线程之间并没有完美的关联,但这使得验证您自己变得非常容易(例如,控件单击底部的一个命名
kdebug
区域以筛选仅用于应用程序操作部分的时间线;等等)。我不可能在这个简短的回答中给出答案,但我可能建议您观看这个视频,它向您展示了如何将代码中的活动与线程、CPU等上的活动相关联。当然,要熟悉这个工具需要稍加尝试(例如,过滤到所讨论的进程,学习识别你的线程和操作系统创建的其他线程,等等),但是它可以帮助识别被阻塞的线程,等等。