基础知识 - 多线程
基本概念
串行:多个任务依次执行,主线程算是比较特殊的一个线程
并行:多任务同时执行,执行效率特别高
并发:多任务轮流依次执行 a任务执行一部分,切到b任务执行一部分,给人的感觉像是多个任务同时执行,但是同一时间最终只有一个任务在被执行

进程和线程
进程:app启动,则开启一个进程,进程和应用是一一对应的关系,开启进程后,可以管理进程的状态变化等
线程:线程是操作系统进行运算调度的最小单位,
GCD
队列:同步队列,并发队列
DISPATCH_QUEUE_SERIAL 串行队列 主队列算是一种比较特殊的串行队列dispatch_get_main_queue
DISPATCH_QUEUE_CONCURRENT 并发队列,全局队列属于并发队列dispatch_get_global_queue,队列开启64个线程
任务
同步执行:dispatch_sync
1、同步添加任务到指定的队列中,在添加的任务执行结束之前,会一直等待,直到队列里面的任务完成之后再继续执行。
2、只能在当前线程中执行任务,不会创建新线程。
异步执行:dispatch_async
1、异步添加任务到指定的队列中,添加完成可以继续执行后面的代码。
2、可以在新的线程中执行任务,可能会创建新线程。

同步任务+主队列会因为队列等待导致的死锁
syncTaskInMainQueue被添加到主队列中,block1,block2也被添加到主队列中,又要同步添加到主队列的任务依次执行,所有block1,block2的执行依赖于syncTaskInMainQueue的执行,而syncTaskInMainQueue中block,block2不执行该方法也没法执行结束,这样就陷入了队列等待导致的死锁
- (void)syncTaskInMainQueue {
NSLog(@"currentThread---%@",[NSThread currentThread]);
NSLog(@"begin");
dispatch_queue_t queue = dispatch_get_main_queue();
//block1
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1---%@",[NSThread currentThread]);
});
//block2
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2---%@",[NSThread currentThread]);
});
NSLog(@"end");
}
线程组
dispatch_group
实现多网络请求并发
dispatch_group_enter 进入组
dispatch_group_leave 退出组
enter leave是成对出现的,如果不是成对,则会一直等待
信号量
dispatch_semaphore 信号量 信号量的值为0时,如果执行wait则会等待,发送sign信号,信号量的值会 1
dispatch_semaphore_create(0)
dispatch_semaphore_sign() 发送信号
dispatch_semaphore_wait() 等待
栅栏函数 - 多读单写
dispatch_barrier_async
dispatch_barrier_sync
在barrier之前的队列会先执行,接着执行barrier队列,最后再执行barrier以后的队列
任务3必须等到1、2都执行完之后才能执行4。
dispatch_queue_t conque1 = dispatch_queue_create("com.helloworld.djx1", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(conque1, ^{
NSLog(@"1");
});
dispatch_async(conque1, ^{
NSLog(@"2");
});
dispatch_barrier_async(conque1, ^{
NSLog(@"3");
});
dispatch_async(conque1, ^{
NSLog(@"4");
});
多读单写 并发队列同一时间可以多个读者,由于barrier特性,只能存在一个写操作,写的同时,保证前面的所有都读完,然后进行写操作,写完成之后,在执行后续的操作
#import "WHObject.h"
@interface WHObject()
@property (nonatomic, strong) dispatch_queue_t dictQueue;//并发队列
@property (nonatomic, strong) NSMutableDictionary *dict;//可变字典
@end
@implementation WHObject
- (instancetype)init {
if(self = [super init]) {
_dictQueue = dispatch_queue_create("com.huangwenhong.queue", DISPATCH_QUEUE_CONCURRENT);
_dict = [NSMutableDictionary dictionary];
}
return self;
}
- (void)huangwenhongmethod {
self.target = [NSObject new];
}
- (id)valueForKey:(NSString *)key {
id __block obj;
dispatch_sync(_dictQueue, ^{//因为有数据 return,所以这里是同步调用
obj = [self.dict valueForKey:key];
});
return obj;
}
- (void)setObject:(id)obj forKey:(id<NSCopying>)key {
//重点:dispatch_barrier_async(),异步栅栏调用;
//只有提交到并行队列才有意义
dispatch_barrier_async(_dictQueue, ^{
[self.dict setObject:obj forKey:key];
});
}
@end
NSOperation/NSOperationQueue
NSOperation、NSOperationQueue 是 iOS 中一种多线程实现方式,实际上是基于 GCD 更高一层的封装,NSOperation 和 NSOperationQueue 分别对应 GCD 的任务和队列。面向对象,比 GCD 更简单易用
addDependency添加依赖关系
创建队列 添加任务到队列 执行队列
有点:
1、 控制开启的最大线程数
2、可以控制队列执行的状态 isFinished/isExecuting/isCanceled
3、可以添加依赖
NSThread
开启常驻线程过程:
1、创建一个线程
2、把线程添加runloop中
3、执行线程
@interface ViewController ()
@property (strong, nonatomic) NSThread *thread;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadStart) object:nil];
[self.thread start];
}
- (void)threadStart{
NSLog(@"%s %@", __func__, [NSThread currentThread]);
//往RunLoop里面添加Source\Timer\Observer 避免runloop里面没有事件执行退出
[[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
NSLog(@"%s ----end----", __func__);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO];
}
// 子线程需要执行的任务
- (void)test
{
NSLog(@"%s %@ 执行了test", __func__, [NSThread currentThread]);
}

浙公网安备 33010602011771号