1 协程是一种比线程更轻量级的存在,如几个进程可以拥有多个线程一样,一个线程可以拥有多个协程.
2 线程的阻塞状态是由操作系统的内核进行切换的,而协程不是被操作系统内核管理,而是完全由程序控制,也就是在用户态执行,不需要像线程那样在用户态和内核态之间来回切换。所以,协程的开销会远远小于线程的开销。和多线程相比,线程的数量越多,协程的性能优势也就越明显
使用协程的优点:
- 协程不是被操作系统内核管理,是在用户态执行,所以节省了线程切换的性能开销
-
使用协程的缺点:
我们需要自己承担协程之间调度的责任。
- 由于协程本质上是在单线程上跑的,也就失去了线程使用多 CPU 的能力,无法利用多核资源。只有将协程和进程配合才可以使用多 CPU。
- 在协程中如果使用了阻塞操作,会阻塞掉整个程序。
开篇我们先来看看coobjc的强大能力:
下面是一个下载图片并在主线程赋值的一个操作,是常规代码.
[NSURLConnection sendAsynchronousRequest:rq queue:nil completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
if (connectionError) {
if (callback) {
callback(nil, nil,connectionError);
}
}
else{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *imageUrl = dict[@"image"];
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]] queue:nil completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
if (connectionError) {
callback(nil, dict,connectionError);
}
else{
UIImage *image = [[UIImage alloc] initWithData:data];
if (callback) {
(image, dict, nil);
}
}
});
}];
});
}
}]
那么我们用协程可以多简单呢?废话不多说,上代码
co_launch(^{
NSData *data = await(downloadDataFromUrl(url));
UIImage *image = await(imageFromData(data));
self.imageView.image = image;
});
三行代码,逻辑很清晰
在付呗项目中采用了大量coobjc结合rac使用的例子,结合我们项目的MVVM架构,对于项目解耦有很大帮助.
小结
coobjc为objc和swift提供了协程能力,以及基于协程的一些便捷的方法和编程范式。但对比Javascript/dart/go等原生支持协程的语言,这种hack的方式添加的语法毕竟不是特别友好。