由于技术的发展,现在搭载多核心处理器的手机系统越来越多。在这些系统上如果要利用其多核心的优势让自己的程序运行速度更快,那免不了要利用多线程技术。更普遍的,如果要让一个耗时很长的操作不至于卡住用户界面,我们一般会把这个操作移交到另一个线程上做。当然,从操作系统的角度上讲,这个办法是(几乎)唯一的办法,没有任何错误。
然而,操作系统对于线程的理解和码农们毕竟不一样。操作系统对于线程的调度能力是普通代码力所不能及的。这展现在几个方面:第一,程序员很难根据核心数量的多少来动态适应自己的线程数量。第二:程序员很难根据核心的负载来动态适应自己线程的优先级。能够对多线程进行最好管理的,一定是操作系统本身。这些都是我们编写优质多线程代码的时候的困难。
面对这种情况,iOS 提供了非常好的解决方案。GCD 和 NSOperationQueue 就是这样的方案。在利用 Dispatch Queue 以及 Operation Queue 的时候有这样几个好处
1.能减少你的用户程序管理线程的开支
2.你可以不用写线程创建相关的代码
3.你可以不用写工作调度相关的代码
4.总的来说,你的代码变的简单了
以 Dispatch Queue 作为例子
void dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
能让程序在另外一个线程上执行 block 中的代码,并且能够保证你提交给 queue 的代码的执行顺序不被打乱。一般来说,多线程编程里的单次任务线程都可以被这个代替。iOS 自身提供了四个全局的并行队列,以及当前非并行的主队列,我们还可以自行创建各种优先级的并行或非并行队列。利用 dispatch_async 和 dispatch_sync 我们可以选择自己的代码究竟在哪个队列里执行。只要做稍微的安排就可以完成要很多行原生的线程编程代码才能完成的工作。
同样的,NSOperationQueue 也能提供类似的功能。然而在接口上来说,GCD 相比 Operation Queue 要更接近于原本的线程,它们所提供的功能也是 GCD 要更丰富一些。
当然,并行处理不仅仅是只有多线程才能做到。一个很简单的例子就是,在这段时间我把 Android 代码翻译到 iOS 的时候,碰到了很多多线程代码。这些多线程代码都是和网络交互相关。而 iOS 所提供的 socket 都是基于 runloop 的并行 socket,这样在每一个主线程的 runloop 里我们都可以根据收到的包以及程序的状态来判断程序下一步应该执行的行为,而不需要真正的刻意把这个交给一个子线程去做。事实上,如果要谈论多线程和 runloop 的优劣的话,我也不敢妄下断言。因为每种方法的出错率还有运行效率也和程序员本身的思维方式和编程习惯有关。虽然在原则上自然是 GCD 最优。但是在普通线程代码和 runloop 里选择的话,我个人偏向 runloop
当然,也有其他的不能使用 NSOperationQueue 以及 GCD 的情况。对于前者来说,自然纯 C 的代码或者 C++ 的代码里是没法用的。而对于后者来说,如果你的代码是 C++ 代码并且需要能直接在 iOS 和 Android 两个平台上运行(就像是许多 OpenGL 代码一样),这种时候的并行编程就只能老老实实的写多线程了。真是悲剧