Jiacheng

aha

野比大雄

Android 的多线程与 iOS 的队列

Jiacheng / 2018-09-20


概述

并发在当前计算机 CPU 架构中一直是处于很关键的地位,能够高效利用 CPU 的计算能力。在手机 APP 开发中,并发一般指一个进程中的多个线程同时执行任务。

不论是 Android 还是 iOS 并发编程都是在系统 API 高度封装下完成的。这里主要总结 Android 与 iOS 中并发编程的异同。

首先两个操作系统都是一个应用对应一个进程(Android 应用有可能是多进程,但是并发编程同样是在单个进程的内部),同样在应用进程中有一个主线程,也称 UI 线程,负责执行 UI 相关的任务,都不能被耗时任务阻塞,一面造成卡顿。从这里也能看出并发编程的必要性,因为实际总会有一些耗时的任务(I/O、网络、复杂运算等)需要执行。所以两者的并发编程都在于如何协调后台线程与主线程以及后台线程与后台线程之间的关系。

另外,两个系统同样地都要面对并发编程所带来的一些问题与挑战,比如,如果两个线程之间是共享资源的(内存中的对象,数据库的数据等),也就是当两者都能够访问或修改,如何保证数据的一致性,协调两个线程之间的冲突,也就是线程安全问题。如果通过互斥锁来保证线程的安全,那么又如何来防止死锁。以及其他一些优先级反转等问题。其实,不论是哪个操作系统平台,只要存在并发编程,都要面临以上这些问题。只不过在不同的平台上,系统封装的 API 有些差异,导致实现并发编程的时候,也会有所差异。

Android

在 Android 开发中,并发编程一般称为多线程开发,UI 线程从一个线程安全的队列里取出要执行的任务,任何线程都可以通过主线程的 Handler 向主线程队列 post 要交给主线程执行的任务(一般是 UI 刷新的任务)。Handler 是 Android 中线程与线程通信的一种机制,每个线程都可以拥有自己的 Handler,可以把它当成线程的信使,别的线程通过它把需要当前线程要执行的任务放到当前线程的队列,而 Handler 同时也负责处理从队列里一个一个出来的任务。

在 Android 的这种机制上,并发线程常规实现就在于,除了系统产生的 UI 线程之外,维护自己的一个线程池(ThreadPoolExecutor),限定线程池中线程的数目,防止由于过多的手动创建线程导致线程爆炸,创建线程是需要成本的,也会占用过多的资源。在执行耗时任务的时候,向线程池中提交任务,而后在耗时任务执行完之后,把要更新的任务通过 handler 提交到主线程即可。

除此之外,Android 在 Thread 和 Handler 之上有提供一些额外的封装帮助实现并发编程,比如 HandlerThread、AsyncTask、IntentService 等,但是整体的机制仍然是没有变的。

如果需要操作线程与线程之间的依赖关系,限制执行顺序,或保证共享资源的线程安全,则需要使用 Thread 类来细分操作。比如使用 synchronized 关键字给对象或方法加锁,保证线程的安全,又或者使用 wait 方法是线程进入等待状态,直到被另一个线程执行完任务后通知唤醒,通过 sleep 使线程休眠等。

可以看出,Android 中并发编程依然是以 Thread 视角为主,结合 Android 提供的 Handler 机制,提供一些常用场景的封装,以及线程池的封装,同时保留了 Java 中一些并发编程的方式(synchronized,wait 等)。

iOS

未完待续…