我们在此代码示例中运行了多少个线程?谁能画出它的流程图?

时间:2016-08-19 18:51:19

标签: objective-c grand-central-dispatch

- (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");
    });
}

1 个答案:

答案 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的区域来过滤应用程序操作的那一部分的时间表;等等。

enter image description here

我无法在这个简短的回答中说明这一点,但我可能会建议观看该视频,它会向您展示如何将代码中的活动与线程,cpus等活动​​相关联。这无疑需要一点点玩使用此工具熟悉它(例如,过滤到相关过程,学习识别线程与操作系统创建的其他线程等),但它可以帮助识别被阻塞的线程等。