什么是线程通信,线程间如何通信,有哪些常见的线程通信方式?可能我们经常听到这个问题,下面关于这个问题,我们来详细的总结一下(收集整理一下网上各位大佬的博客汇总)。
一、问题的理解
- 一个线程传递数据给另一个线程。
- 在一个线程中执行完特定的任务之后,转到另一个线程继续执行任务。
二、NSObject对象的线程通信方式
1. 在主线程添加执行方法
withObject
id
类型的参数可以传递给调用的方法 waitUntilDone
设置YES
,代表等待当前线程执行完毕。
[self performSelectorOnMainThread:@selector(doSomething:) withObject:@[@"添加到主线程"] waitUntilDone:YES];
2. 把需要执行的操作放到后台线程
[self performSelectorInBackground:@selector(doSomething:) withObject:@[@"后台线程"]];
三、GCD通信方式
1. 回归主线程
很多时候在子线程处理完数据需要回到主线程更新UI的时候,可以调用如下方法。
dispatch_async(dispatch_get_main_queue(), ^{
// doSomething
});
2. 全局队列
dispatch_get_global_queue(long identifier, unsigned long flags)
函数有两个参数,第一个identifier
设置全局队列优先级,有四个优先级,分别是
DISPATCH_QUEUE_PRIORITY_HIGH
全局队列 高优先级
DISPATCH_QUEUE_PRIORITY_DEFAULT
全局队列 默认优先级
DISPATCH_QUEUE_PRIORITY_LOW
全局队列 低优先级
DISPATCH_QUEUE_PRIORITY_BACKGROUND
全局队列 后台优先级
第二个参数是保留参数,指定为0,在开发中遇到一些大批量数据处理查询等操作可以使用如下方法。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// doSomething
});
3. 同步操作
一般用于在开发中处理一些单线程同步的操作。
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// doSomething
});
四、 NSThread通信方式
1. 自定义线程
自定义线程,将当前数据转移到指定的线程去操作,但是这种方法经常会遇到线程退出造成崩溃,不建议使用。
NSThread *thread = [[NSThread alloc] init];
[thread start];
[self performSelector:@selector(doSomething:) onThread:thread withObject:@[@"自创线程"] waitUntilDone:YES];
下面这种方法可以避免线程退出情况
NSThread *thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(dothing:) object:@[@"自创线程2"]];
[thread2 start];
还有一种方法可以直接把响应的操作放到子线程,这种方法会立即在子线程执行响应的方法,与performSelectorInBackground:
方法等价。
[NSThread detachNewThreadSelector:@selector(backGroundMethod) toTarget:self withObject:@[@"自创线程3"]];
当然,我们也可以增加一个特殊的线程常驻RunLoop,防止线程退出
NSThread *runLoopThread = [[NSThread alloc] initWithTarget:self selector:@selector(onRunLoop) object:nil];
[runLoopThread start];
[self performSelector:@selector(dothingOnRunLoop:) onThread:runLoopThread withObject:@[@"常驻RunLoop线程"] waitUntilDone:YES];
// 常驻runLoop
- (void)onRunLoop {
@autoreleasepool {
[NSThread currentThread].name = @"常驻RunLoop线程";
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}
// 在runloop上执行操作
- (void)dothingOnRunLoop:(id)param {
// 可以在此打断点测试线程是否已经加入runloop
NSLog(@"跑在runloop上的线程: %@", param);
}
五、NSOperationQueue通信方式
还有NSOperationQueue
也可以用于线程通信,不过使用的时候不多,比如在主队列增加执行操作
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"在主队列增加执行Block");
}];
六、总结
以上就是iOS中常用的几种通信方式,在项目中可以根据需求灵活使用。