CPU同一时间只能处理有限数目的线程,赋予线程怎样的优先级,将决定其最终在CPU上得以执行的顺序
光头哥回归啦!读信的样子简直不要太萌!
Video Link


Thread Scheduling

线程调度是现代计算机系统必不可少的功能,Android做为独特的移动系统,在线程调度上,还有一些它与众不同的特性。

Android系统中对于线程优先级的考虑,还会包括以下方面:

  • Activity生命周期
  • 是否可见
  • Activity在前台还是运行

Visible vs Invisible

CPU时间的90%左右,都是用以处理界面展示中的线程,只有约10%留给了后台线程


拼爹的线程

在线程的世界里,一样要拼爹——新创建的线程,其优先级与创建它的线程相同。

也就是说,如果UI Thread创建了20个Worker Thread,那么这20个Worker Thread都具有相同的优先级,它们会平等竞争CPU时间。

这其实是很不好的,我们知道哪些工作更重要,哪些工作相比于其它不那么重要,所以我们要主动设置线程优先级,让那些具有更高优先级的线程优先得到执行。


Priority

1
android.os.Process.setThreadPriority(int);

上面的方法接受-20~24闭区间内所有的整数作为参数,数值越小,优先级越高。为甚么采用负数呢?数值越低,表示这个线程越没有耐心,情绪越暴躁,越急切希望得到执行。

android.os.Process中为我们定义了一些表示线程优先级的常量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* Standard priority of application threads.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_DEFAULT = 0;

/*
* ***************************************
* ** Keep in sync with utils/threads.h **
* ***************************************
*/

/**
* Lowest available thread priority. Only for those who really, really
* don't want to run if anything else is happening.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_LOWEST = 19;

/**
* Standard priority background threads. This gives your thread a slightly
* lower than normal priority, so that it will have less chance of impacting
* the responsiveness of the user interface.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_BACKGROUND = 10;

/**
* Standard priority of threads that are currently running a user interface
* that the user is interacting with. Applications can not normally
* change to this priority; the system will automatically adjust your
* application threads as the user moves through the UI.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_FOREGROUND = -2;

/**
* Standard priority of system display threads, involved in updating
* the user interface. Applications can not
* normally change to this priority.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_DISPLAY = -4;

/**
* Standard priority of the most important display threads, for compositing
* the screen and retrieving input events. Applications can not normally
* change to this priority.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_URGENT_DISPLAY = -8;

/**
* Standard priority of audio threads. Applications can not normally
* change to this priority.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_AUDIO = -16;

/**
* Standard priority of the most important audio threads.
* Applications can not normally change to this priority.
* Use with {@link #setThreadPriority(int)} and
* {@link #setThreadPriority(int, int)}, <b>not</b> with the normal
* {@link java.lang.Thread} class.
*/
public static final int THREAD_PRIORITY_URGENT_AUDIO = -19;

此外,还有两个常量用于提高/降低优先级,记住,负数越小,优先级越高(more favorable)。

1
2
3
4
5
6
7
8
9
/**
* Minimum increment to make a priority more favorable.
*/
public static final int THREAD_PRIORITY_MORE_FAVORABLE = -1;

/**
* Minimum increment to make a priority less favorable.
*/
public static final int THREAD_PRIORITY_LESS_FAVORABLE = +1;

有了上面的知识,你就可以在UI Thread启动Worker Thread时,通过setPriority(THREAD_PRIORITY_DEFAULT + THREAD_PRIORITY_LESS_FAVORABLE * n)的方式,酌情降低Worker Thread的优先级了。


That’s How We Did It!

还记得之前我们总是提到的 AsyncTask/HandlerThread/ThreadPool/IntentService 么?其中AsyncTask和IntentService已经为自动我们实现了“降低Worker Thread优先级”的功能,我们无需额外设置。而另外两种则没有这么周到,我们需要主动设置工作线程优先级。


===Ending===