多线程三: NSThread 面试题

- (void)viewDidLoad {
   [super viewDidLoad];
   NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"1");
    }];
    [thread start];
    
    [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];
}

- (void)test {
    NSLog(@"2");
}

打印结果:
1
然后崩溃
错误信息是:
Terminating app due to uncaught exception ‘NSDestinationInvalidException’, reason: ‘*** -[ViewController performSelector:onThread:withObject:waitUntilDone:modes:]: target thread exited while waiting for the perform’


这是因为

  • test 方法是放在 thread 线程中执行的;
  • 当 程序执行到 [thread start] 方法时,initWithBlock 中的 内容已经执行完毕,thread 线程就销毁了。
  • 所以当 执行 test 方法时, 因 thread 线程已经被销毁。自然就崩溃了。

可以添加 runloop 来解决此问题。

    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"1");
        [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }];
    [thread start];
    
    [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];

如果代码改成 后 执行 [thread start ] 会发生什么 ?

- (void)getNSThreadFirst {
    NSLog(@"123");
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"1");
    }];
    
    NSLog(@"456");
    [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:YES];
    
    NSLog(@"789");
    [thread start];
    
    NSLog(@"098");
}

执行结果:
在这里插入图片描述

这是因为 相互等待,因为 waitUntilDone = yes 。


把 waitUntilDone 改成 No.

- (void)getNSThreadFirst {
    NSLog(@"123");
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSLog(@"1");
    }];
    
    NSLog(@"456");
    [self performSelector:@selector(test) onThread:thread withObject:nil waitUntilDone:NO];
    
    NSLog(@"789");
    [thread start];
    
    NSLog(@"098");
}

执行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/M316625387/article/details/83818758