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

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 中,值越小,优先级越高。误用了就会出现错误。

**PS:更多精彩内容,请查看 --> 《Android 开发》
**PS:更多精彩内容,请查看 --> 《Android 开发》
**PS:更多精彩内容,请查看 --> 《Android 开发》

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卜大爷

觉得不错的可以给我加油哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值