线程调度与线程调度模型
任意时刻,只有一个线程占用 CPU,处于运行状态。而多线程并发执行就是轮流获取 CPU 执行权。
- 分时调用模型
轮流获取 CPU 执行权,均分 CPU 执行时间。
- 抢占式调度模型
优先级高的线程优先获取 CPU 执行权,这也是
JVM
采用的线程调度模型。
nice value
nice valuenice value 表示进程的优先级,nice value 越小,线程优先级越高。这个值是在 Process 类中定义的。默认的 THREAD_PRIORITY_DEFAULT,值为0.
下面来关注一下哪些异步框架如何设置这些 nice value 。
- HanlderThread
- AsyncTask
cgroup(control group)
借鉴了 Linux ,它是更严格的群组调度策略,保证前台进程
获取更多的 CPU。那些手动设置优先级比较低的线程或者不在前台运行的应用程序的线程会被放入后台 group ,后台 group 也是可以被 CPU 调度运行,只是获取 CPU 执行权的概率会比较低,这样就不会影响到前台group 的运行。
所以说需要设置要对应的 nice value ,因为该值会影响到线程获取 CPU 执行权的概率。
CPU 密集型与 IO 密集型
CPU 密集型
大量的计算,消耗CPU资源,例如视频进行高清解码,为了重复利用 CPU 资源,应该将线程数量设置为CPU的核心数+1。
IO 密集型
网络、磁盘IO,这时线程大多数时间是阻塞等待 IO 完成的,因为 IO 操作是不占用 CPU 的,为了提高线程的利用率,尽可能的创建更多的任务,这样 CPU 的效率就越高,但是这个数量是有限制的,不能无限制大,线程数 = 2*CPU 核心数。
多线程优化的注意点
- 线程具有继承性
在 UI 线程中如果创建子线程,那么该线程的优先级是和 UI 线程一样的,因此 UI 线程获取到 CPU 执行权的机率肯定会渐低。
- 根据任务的性质来设置线程数量,具体参考上面的 CPU 密集型和 IO 密集型的知识点。
Android 的异步方式
- 直接使用 Thread
这种方式是最简单的,但是也是最不推荐的方式,因为频繁的创建和销毁,增大了系统资源的开销,并且通过这种方式创建的线程无法得到控制,也不能被复用。
- HandlerThread
内部结合了 Handler 和 Thread ,特点就是串行执行每一个任务。
- IntentService
内部是使用 HandlerThread ,因此具备 HandlerThread 的特点,因为继承至 Service ,因此优先级比较高,不容易被系统杀死,它就相当于一个可以跑异步任务的 service 。
- AsyncTask
内部提供了线程池,在异步任务执行前,执行中,执行完成都会相应的回调。
- 线程池
Executors 工具类提供了很多系统内置好的线程池,当然也可以通过自己去配置线程池的参数。
- RxJava
可以通过任务的类型,选择 CPU 密集型的还是 IO 密集型的线程池去执行。
参考
https://droidyue.com/blog/2015/09/05/android-process-and-thread-schedule-nice/
本文是笔者学习之后的总结,方便日后查看学习,有任何不对的地方请指正。
记录于 2019年4月16号
网友评论