Linux中,使用nice value(以下成为nice值)来设定一个进程的优先级,系统任务调度器根据nice值合理安排调度。
nice的取值范围为-20到19。
通常情况下,nice的默认值为0。视具体操作系统而定。
nice的值越大,进程的优先级就越低,获得CPU调用的机会越少,nice值越小,进程的优先级则越高,获得CPU调用的机会越多。
一个nice值为-20的进程优先级最高,nice值为19的进程优先级最低。
父进程fork出来的子进程nice值与父进程相同。父进程renice,子进程nice值不会随之改变。
线程调度
虽然对于进程的优先级,我们无法控制,但是我们可以控制进程中的线程的优先级。在Android中有两种线程的优先级,一种为Android API版本,另一种是 Java 原生版本。
- Android API
Process优先级:priority:负20 ------> +19 ,对应最高优先级------> 最低优先级。
Android中的线程优先级别目前规定了如下,了解了进程优先级与nice值的关系,那么线程优先级与值之间的关系也就更加容易理解。
THREAD_PRIORITY_DEFAULT,默认的线程优先级,值为0。
THREAD_PRIORITY_LOWEST,最低的线程级别,值为19。
THREAD_PRIORITY_BACKGROUND 后台线程建议设置这个优先级,值为10。
THREAD_PRIORITY_FOREGROUND 用户正在交互的UI线程,代码中无法设置该优先级,系统会按照情况调整到该优先级,值为-2。
THREAD_PRIORITY_DISPLAY 也是与UI交互相关的优先级界别,但是要比THREAD_PRIORITY_FOREGROUND优先,代码中无法设置,由系统按照情况调整,值为-4。
THREAD_PRIORITY_URGENT_DISPLAY 显示线程的最高级别,用来处理绘制画面和检索输入事件,代码中无法设置成该优先级。值为-8。
THREAD_PRIORITY_AUDIO 声音线程的标准级别,代码中无法设置为该优先级,值为 -16。
THREAD_PRIORITY_URGENT_AUDIO 声音线程的最高级别,优先程度较THREAD_PRIORITY_AUDIO要高。代码中无法设置为该优先级。值为-19。
THREAD_PRIORITY_MORE_FAVORABLE 相对THREAD_PRIORITY_DEFAULT稍微优先,值为-1。
THREAD_PRIORITY_LESS_FAVORABLE 相对THREAD_PRIORITY_DEFAULT稍微落后一些,值为1。
使用Android API为线程设置优先级也很简单,只需要在线程执行时调用android.os.Process.setThreadPriority方法即可。这种在线程运行时进行修改优先级,效果类似renice。
new Thread () {
@Override
public void run() {
super.run();
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
}.start();
- Java原生API
Java优先级:priority:1 --------------> 10,最低优先级 -----------> 最高优先级。
Java为Thread提供了三个级别的设置,
MAX_PRIORITY,相当于android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY,值为10。
MIN_PRIORITY,相当于android.os.Process.THREAD_PRIORITY_LOWEST,值为0。
NORM_PRIORITY,相当于android.os.Process.THREAD_PRIORITY_DEFAULT,值为5。
使用setPriority我们可以为某个线程设置优先级,使用getPriority可以获得某个线程的优先级。
Runnable r = ....
Thread thread = new Thread(r);
thread.setPriority(Thread.MAX_PRIORITY);
在Android系统中,不建议使用Java原生的API,因为Android提供的API划分的级别更多,更适合在Android系统中进行设定细致的优先级。 注意Android API的线程优先级和Java原生API的优先级是相对独立的,比如使用android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)后,使用Java原生API,Thread.getPriority()得到的值不会改变。如下面代码:
new Thread() {
@Override
public void run() {
super.run();
Log.i(LOGTAG, "Java Thread Priority Before=" + Thread.currentThread().getPriority());
Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
Log.i(LOGTAG, "Java Thread Priority=" + Thread.currentThread().getPriority());
}
}.start();
上述代码的运行日志为
I/MainActivity( 3679): Java Thread Priority Before=5
I/MainActivity( 3679): Java Thread Priority=5
该用谁?
建议使用Process.setThreadPriority(int priority)
分析ANR 对应的日志文件 /data/anr/traces.txt 时,会遇到两个权限