多執行緒三: NSThread 面試題
阿新 • • 發佈:2018-11-07
- (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");
}
執行結果: