- (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区域以筛选仅用于应用程序操作部分的时间线;等等)。
objective-c - 在此代码示例中,我们运行多少个线程?谁能画出流程图?-LMLPHP
我不可能在这个简短的回答中给出答案,但我可能建议您观看这个视频,它向您展示了如何将代码中的活动与线程、CPU等上的活动相关联。当然,要熟悉这个工具需要稍加尝试(例如,过滤到所讨论的进程,学习识别你的线程和操作系统创建的其他线程,等等),但是它可以帮助识别被阻塞的线程,等等。

08-05 22:13