- (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");
});
}
答案 0 :(得分:4)
每个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中列出的这些唯一标识符相关联,以便它们在“兴趣点”部分中显示为“区域”。然后,您可以使用Instruments中的“系统跟踪”工具,您可以看到发生了什么。这些命名区域及其相关线程之间没有完美的关联,但它使得自己验证非常容易(例如 control - 点击底部的一个名为kdebug
的区域来过滤应用程序操作的那一部分的时间表;等等。
我无法在这个简短的回答中说明这一点,但我可能会建议观看该视频,它会向您展示如何将代码中的活动与线程,cpus等活动相关联。这无疑需要一点点玩使用此工具熟悉它(例如,过滤到相关过程,学习识别线程与操作系统创建的其他线程等),但它可以帮助识别被阻塞的线程等。