likes
comments
collection
share

Android中如何调高子进程的优先级

作者站长头像
站长
· 阅读数 29

这是我们群内一位小伙伴问到的面试问题,这里拿卜大爷的一篇文章用来解析,实属于借花献佛了......

Android 中设置线程优先级的正确方式(2种方法)


在 Android 中,有两种常见的设置线程优先级的方式:

  1. 第一种,使用 Thread 类实例的 setPriority 方法,来设置线程优先级。
  2. 第二种,使用 Process 类的 setThreadPriority 方法,来设置线程优先级。

这两种设置线程的优先级,一种是 Java 原生版本,另一种是 Android API 版本。这两种方式是不同的,Android 更推荐使用第二种方式。

使用 Thread 类的 setPriority 方法

使用 Thread 类实例的 setPriority 方法,来设置线程优先级,这种方式来源于 Java,他可以通过 Java 的 Thread 属性来设置线程优先级。

  • setPriority 方法的参数是 Thread 的静态常量:
    /**
     * The minimum priority that a thread can have.
     */
    public final static int MIN_PRIORITY = 1;

   /**
     * The default priority that is assigned to a thread.
     */
    public final static int NORM_PRIORITY = 5;

    /**
     * The maximum priority that a thread can have.
     */
    public final static int MAX_PRIORITY = 10;

setPriority 方法修改线程优先级时,参数范围必须在 MIN_PRIORITY 和 MAX_PRIORITY 范围之间,如果超过该范围,将抛出错误。设置成功时,此线程的优先级将设置为指定的参数和该线程的线程组的最大允许优先级中的较小者。

也就是说,用 Thread 实例对象的 setPriority 设置线程优先级,范围为 1~10。

我们来看一个示例:

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {

            }
        });
        thread.setPriority(Thread.MIN_PRIORITY);
        thread.start();

使用 Process 类的 setThreadPriority 方法

使用 Process 类(android.os.Process)的 setThreadPriority 方法,来设置线程优先级,这是 Android 推荐的方式。

  • setThreadPriority 的参数:
    //应用程序线程的标准优先级
    public static final int THREAD_PRIORITY_DEFAULT = 0;
    //最低可用优先级,仅针对那些真的不想在发生任何其他事情的情况下运行的任务。
    public static final int THREAD_PRIORITY_LOWEST = 19;
    //标准后台优先级,优先级略低于正常优先级,它对用户界面的影响非常小。
    public static final int THREAD_PRIORITY_BACKGROUND = 10;
    //用户正在进行交互的 UI 线程优先级。当用户在界面之间进行切换时,系统将自动调整应用线程的优先级。该优先级应用程序不能自己设置(也就是代码中不能设置)。
    public static final int THREAD_PRIORITY_FOREGROUND = -2;
    //系统显示线程的优先级,该优先级应用也不能自己设置。
    public static final int THREAD_PRIORITY_DISPLAY = -4;
    //最重要的显示线程的优先级,用于合成屏幕和检索输入事件。应用程序不能更改为此优先级。
    public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8;
    //视频线程的标准优先级。应用程序不能更改为此优先级。
    public static final int THREAD_PRIORITY_VIDEO = -10;
    //音频线程的标准优先级。应用程序不能更改为此优先级。
    public static final int THREAD_PRIORITY_AUDIO = -16;
    //最重要的音频线程的标准优先级。应用程序不能更改为此优先级。
    public static final int THREAD_PRIORITY_URGENT_AUDIO = -19;

setThreadPriority 的参数同样是一个 int 值,常量定义在 Process 类中。

使用 Android API 为线程设置优先级也很简单,只需要在线程执行时调用 android.os.Process.setThreadPriority 方法即可。这种在线程运行时进行修改优先级,效果类似 renice。

示例代码:

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
            }
        });
        thread.start();

Linux 系统的 nice

Linux 中,使用 nice 值来设定一个进程的优先级,系统任务调度器根据 nice 值合理安排调度。而 Android 系统是基于 Linux 内核开发的,它的线程的内部实现,也是基于 Linux 的轻量级进程来实现的。

我们来看 nice 的一些特征:

  • nice 的取值范围为 -20 到 19 差不多对应了 Android API 的线程优先级的取值范围。
  • nice 的值越大,进程的优先级就越低,获得 CPU 调用的机会越少,nice 值越小,进程的优先级则越高,获得 CPU 调用的机会越多。
  • 一个 nice 值为 -20 的进程优先级最高,nice 值为 19 的进程优先级最低。
  • 父进程 fork 出来的子进程继承了父进程的优先级。

在 Android 中,无论通过什么方式设置的线程优先级,其实本质上都是通过 native 层,设置 nice 的值来实现的。

对应关系

MAX_PRIORITY ——> 相当于 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY。
 
MIN_PRIORITY ——> 相当于 android.os.Process.THREAD_PRIORITY_LOWEST。
 
NORM_PRIORITY ——> 相当于 android.os.Process.THREAD_PRIORITY_DEFAULT。

在 Android 系统中,不建议使用 Java 原生的 API 设置线程优先级,因为 Android 提供的 API 划分的级别更多,更适合在 Android 系统中进行设定细致的优先级。

线程优先级的注意事项

  • Android API 的线程优先级和 Java 原生 API 的优先级是相对独立的

Android API 的线程优先级和 Java 原生 API 的优先级是相对独立的,比如使用 android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND) 后,使用 Java 原生 Thread.getPriority() 得到的值不会改变。

  • ANR 信息中的线程优先级

我们在分析 ANR 日志时需要注意,在下面的 ANR 日志信息中,prio=5 中 proi 的值对应的 Java 原生 API 的线程优先级。而 nice=-2 中的 nice 表示的 Android API 版本的线程优先级。

"main" prio=5 tid=1 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x41690f18 self=0x4167e650
  | sysTid=1665 nice=-2 sched=0/0 cgrp=apps handle=1074196899
  | state=S schedstat=( 0 0 0 ) utm=5764 stm=3654 core=2
  #00  pc 00022624  /system/lib/libc.so (__futex_syscall3+8)
  #01  pc 0000f054  /system/lib/libc.so (__pthread_cond_timedwait_relative+48)
  #02  pc 0000f0b4  /system/lib/libc.so (__pthread_cond_timedwait+64)


  • Java 原生 API 中,值越大,优先级越高;而在 Android 原生 API 中,值越小,优先级越高

一定不要混用了线程优先级设置中的常量,Java 原生 API 中,值越大,优先级越高;而在 Android 原生 API 中,值越小,优先级越高。误用了就会出现错误。

总结


  1. 在 Android 中,有两种常见的设置线程优先级的方式:第一种,使用 Thread 类实例的 setPriority 方法,来设置线程优先级。第二种,使用 Process 类的 setThreadPriority 方法,来设置线程优先级。
  2. Java 原生的方法 setPriority 修改线程优先级时,参数范围必须在 MIN_PRIORITY 和 MAX_PRIORITY 范围之间,如果超过该范围,将抛出错误。设置成功时,此线程的优先级将设置为指定的参数和该线程的线程组的最大允许优先级中的较小者。
  3. 使用 Android API 为线程设置优先级也很简单,只需要在线程执行时调用 android.os.Process.setThreadPriority 方法即可。这种在线程运行时进行修改优先级,效果类似 renice。
  4. 在 Android 中,无论通过什么方式设置的线程优先级,其实本质上都是通过 native 层,设置 nice 的值来实现的。
  5. Android API 的线程优先级和 Java 原生 API 的优先级是相对独立的。
  6. ANR 信息中的线程优先级,nice 代表了实际的线程优先级。
  7. 一定不要混用了线程优先级设置中的常量,Java 原生 API 中,值越大,优先级越高;而在 Android 原生 API 中,值越小,优先级越高。误用了就会出现错误。

今日分享到此结束,对你有帮助的话,点个赞再走呗,每日一个面试小技巧

关注公众号:Android老皮 解锁  《Android十大板块文档》 ,让学习更贴近未来实战。已形成PDF版

内容如下

1.Android车载应用开发系统学习指南(附项目实战) 2.Android Framework学习指南,助力成为系统级开发高手 3.2023最新Android中高级面试题汇总+解析,告别零offer 4.企业级Android音视频开发学习路线+项目实战(附源码) 5.Android Jetpack从入门到精通,构建高质量UI界面 6.Flutter技术解析与实战,跨平台首要之选 7.Kotlin从入门到实战,全方面提升架构基础 8.高级Android插件化与组件化(含实战教程和源码) 9.Android 性能优化实战+360°全方面性能调优 10.Android零基础入门到精通,高手进阶之路

转载自:https://juejin.cn/post/7270648629378940968
评论
请登录