Threads on Android

Android中的线程

序: 
      阅读英文原版,受益匪浅。修饰词形容惟妙惟肖。 
      其中举例之图,经典,且秒不可言。亦当细细品味之。 
      翻译为谷歌翻译。 重点单词日后补上,可用有道词典积累,认识的单词会越来越多
      不认识的单词亦会越来越少,而翻译并不能完全体现作者本意,亦可备注评论之上。
      佛祖拈花 迦叶一笑。观者千人,体会亦千面。 所思所想亦可评论,互相交流。 
      亦可以锻炼英文文档阅读能力。

整理如下。

Every Android application is started with numerous threads that are bundled with the Linux process and the Dalvik VM to manage its internal execution. But the application is exposed to system threads, like the UI and binder threads, and creates background threads of its own. In this chapter, we’ll get under the hood of threading on the Android platform, examining the following: 
• Differences and similarities between UI, binder, and background threads 
• Linux thread coupling 
• How thread scheduling is affected by the application process rank 
• Running Linux threads

每个Android应用程序都启动了许多与Linux进程和Dalvik VM捆绑在一起的线程来管理其内部执行。 但应用程序暴露于系统线程,如UI和绑定线程,并创建自己的后台线程。 在本章中,我们将介绍Android平台上的线程,并检查以下内容: 
•UI,binder和后台线程之间的差异和相似之处 
•Linux线程耦合 
•线程调度如何受到应用程序进程排名的影响 
•运行Linux线程

Android Application Threads 
All application threads are based on the native pthreads in Linux with a Thread representation in Java, but the platform still assigns special properties to threads that make them differ. From an application perspective, the thread types are UI, binder, and background threads.

Android应用主题 
所有应用程序线程都是基于Java中的线程表示形式的Linux中的本机pthread,但该平台仍然为使其不同的线程分配特殊属性。 从应用程序的角度来看,线程类型是UI,binder和后台线程。

UI Thread 
The UI thread is started on application start and stays alive during the lifetime of the Linux process. The UI thread is the main thread of the application, used for executing Android components and updating the UI elements on the screen. If the platform detects that UI updates are attempted from any other thread, it will promptly notify the application by throwing a CalledFromWrongThreadException. This harsh platform 
behavior is required because the Android UI Toolkit is not thread safe, so the runtime allows access to the UI elements from one thread only.

UI线程 
UI线程在应用程序启动时启动,并在Linux进程的生命周期内保持活动状态。 UI线程是应用程序的主线程,用于执行Android组件并更新屏幕上的UI元素。 如果平台检测到从任何其他线程尝试UI更新,它将立即通过抛出CalledFromWrongThreadException来通知应用程序。 这是一个苛刻的平台行为,因为Android UI Toolkit不是线程安全的,所以运行时允许只从一个线程访问UI元素。

UI elements in Android are often defined as instance fields of activ‐ ities, so they constitute a part of the object’s state. However, access to those elements doesn’t require synchronization because UI elements can be accessed only from the UI thread. In other words, the run- time enforces a single-threaded environment for UI elements, so they are not susceptible to concurrency problems.

Android中的UI元素通常定义为活动的实例字段,因此它们构成对象状态的一部分。 然而,访问这些元素不需要同步,因为只能从UI线程访问UI元素。 换句话说,运行时为UI元素强制执行单线程环境,因此它们不会受到并发问题的影响。

The UI thread is a sequential event handler thread that can execute events sent from any other thread in the platform. The events are handled serially and are queued if the UI thread is occupied with processing a previous event. Any event can be posted to the UI thread, but if events are sent that do not explicitly require the UI thread for execution, the UI-critical events may have to wait in the queue before being processed and before responsiveness is decreased.

UI线程是可以执行从平台中任何其他线程发送的事件的顺序事件处理程序线程。 事件被串行处理,并且如果UI线程被处理前一个事件占用,则排队。 任何事件都可以发布到UI线程,但是如果发送的事件不明确地要求UI线程执行,则UI关键事件可能必须在被处理之前等待队列,并且响应性降低之前。 
“Android Message Passing” on page 47 describes event handling in detail. 
第47页上的“Android消息传递”详细描述了事件处理。

Binder Threads 
Binder threads are used for communicating between threads in different processes. Each process maintains a set of threads, called a thread pool, that is never terminated or recreated, but can run tasks at the request of another thread in the process. These threads handle incoming requests from other processes, including system services, intents, content providers, and services. When needed, a new binder thread will be created to handle the incoming request. In most cases, an application does not have to be con‐ cerned about binder threads because the platform normally transforms the requests to use the UI thread first. The exception is when the application offers a Service that can be bound from other processes via an AIDL interface. Binder threads are discussed more thoroughly in Chapter 5.

粘合线程 
线程线程用于在不同进程中的线程之间进行通信。 每个进程维护一组线程,称为线程池,从未终止或重新创建,但可以根据进程中另一个线程的请求运行任务。 这些线程处理来自其他进程的传入请求,包括系统服务,意图,内容提供者和服务。 当需要时,将创建一个新的绑定线程来处理传入的请求。 在大多数情况下,应用程序不必关心绑定线程,因为平台通常会先转换使用UI线程的请求。 例外是当应用程序提供可以通过AIDL接口从其他进程绑定的服务时。 第5章中更详细地讨论了粘结螺纹。

Background Threads 
All the threads that an application explicitly creates are background threads. This means that they have no predefined purpose, but are empty execution environments waiting to execute any task. The background threads are descendants of the UI thread, so they inherit the UI thread properties, such as its priority. By default, a newly created process doesn’t contain any background threads. It is always up to the application itself to create them when needed.

后台线程 
应用程序显式创建的所有线程都是后台线程。 这意味着它们没有预定义的目的,而是等待执行任何任务的空执行环境。 后台线程是UI线程的后代,因此它们继承UI线程属性,例如其优先级。 默认情况下,新创建的进程不包含任何后台线程。 应用程序本身在需要时创建它们是始终如一的。 
The second part of this book, Part II, is all about creating back‐ ground threads. 
本书第二部分第二部分是关于创建背景线程的。

A background thread created here in the application would look like this in the ps -t output. The last field is the name. The thread name, by default, ends with the number assigned by the runtime to the thread as its ID: 
u0_a72 4283 4257 320304 34540 ffffffff 00000000 S Thread-12412 
In the application, the use cases for the UI thread and worker threads are quite different, but in Linux they are both plain native threads and are handled equally. The constraints on the UI thread—that it should handle all UI updates—are enforced by the Window Manager in the Application Framework and not by Linux.

在应用程序中创建的后台线程将在ps -t输出中看起来像这样。 最后一个字段是名称。 默认情况下,线程名称以运行时分配给线程的号码作为其ID: 
u0_a72 4283 4257 320304 34540 ffffffff 00000000 S Thread-12412 
在应用程序中,UI线程和工作线程的用例是完全不同的,但是在Linux中它们都是纯本地线程,并且被平等地处理。 UI线程的限制 - 它应该处理所有UI更新 - 由应用程序框架中的Window Manager执行,而不是由Linux执行。

The Linux Process and Threads 
The execution of long operations on background threads on Android can be handled in many ways, but no matter how the application implements the execution mechanism, the threads, in the end, are always the same on the operating system level. The Android platform is a Linux-based OS, and every application is executed as a Linux application in the OS. Both the Android application and its threads adhere to the Linux execution environment. As we will see, knowledge of the Linux environment helps us not only to grasp and investigate the application execution, but also to improve our applications’ performance.

Linux进程和线程 
在Android上的后台线程上执行长操作可以通过多种方式进行处理,但无论应用程序如何实现执行机制,线程在操作系统级别上总是相同的。 Android平台是基于Linux的操作系统,每个应用程序都是作为操作系统中的Linux应用程序执行的。 Android应用程序及其线程都遵守Linux执行环境。 我们将看到,Linux环境的知识有助于我们不仅要掌握和调查应用程序的执行情况,还可以提高应用程序的性能。

Each running application has an underlying Linux process, forked from the prestarted Zygote process, which has the following properties: 
User ID (UID) 
A process has a unique user identifier that represents a user on a Linux system. Linux is a multiuser system, and on Android, each application represents a user in this system. When the application is installed, it is assigned a user ID. 
Process identifier (PID) 
A unique identifier for the process. 
Parent process identifier (PPID) 
After system startup, each process is created from another process. The running system forms a tree hierarchy of the running processes. Hence, each application process has a parent process. For Android, the parent of all processes is the Zygote. 
Stack 
Local function pointers and variables. 
Heap 
The address space allocated to a process. The address space is kept private to a process and can’t be accessed by other processes.

每个正在运行的应用程序都有一个底层的Linux进程,从预先分配的Zygote进程分支,它具有以下属性: 
用户ID(UID) 
一个进程有一个唯一的用户标识符,表示Linux系统上的一个用户。 Linux是一个多用户系统,在Android上,每个应用程序都代表了该系统中的用户。 安装应用程序后,会分配一个用户ID。 
进程标识符(PID) 
进程的唯一标识符。 
父进程标识符(PPID) 
系统启动后,每个进程都是从另一个进程创建的。 运行的系统形成运行进程的树状层次结构。 因此,每个应用进程都有一个父进程。 对于Android,所有进程的父级都是Zygote。 
堆 
局部函数指针和变量。 
堆 
分配给进程的地址空间。 地址空间对进程保持私有,不能被其他进程访问。

Finding Application Process Information 
The process information of a running application is retrieved by the ps (process status) command, which you can call from the ADB shell. The Android ps command retrieves process information just as it would on any Linux distribution. However, the set of options is different than the traditional Linux version of ps: 
-t 
Shows thread information in the processes 
-x 
Shows time spent in user code (utime) and system code (stime) in “jiffies,” which typically is units of 10 ms. 
-p 
Shows priorities. 
-P 
Shows scheduling policy, normally indicating whether the application is executing in the foreground or background. 
-c 
Shows which CPU is executing the process.

name | pid 
Filter on the application’s name or process ID. Only the last defined value is used. 
You can also filter through the grep command. For instance, executing the ps command for a com.eat application1 process would look like this: 
$ adb shell ps | grep com.eat 
USER PID PPID VSIZE RSS WCHAN PS NAME 
u0_a72 4257 144 320304 34540 ffffffff 00000000 S com.eat 
From this output, we can extract the following interesting properties of the com.eat application: 
• UID: u0_a72 
• PID: 4257 
• PPID: 144 (process number of the parent, which in the case of an Android appli‐ cation is always the Zygote) 
Another way of retrieving process and thread information is with DDMS2 in the An‐ droid tools.

  1. I have used the string EAT to create a namespace for applications in this book. The string is an acronym of the book’s title.

查找申请流程信息 
正在运行的应用程序的进程信息可以通过ps(进程状态)命令检索,您可以从ADB shell调用它。 Android ps命令与任何Linux发行版一样检索进程信息。但是,这套选项与传统的Linux版本的ps不同: 
-t 
显示进程中的线程信息 
-X 
显示在“jiffies”中的用户代码(utime)和系统代码(stime)中花费的时间,通常为10 ms的单位。 
-p 
显示优先级 
-P 
显示调度策略,通常指示应用程序是在前台还是后台执行。 
-C 
显示哪个CPU正在执行该进程。

名称| PID 
过滤应用程序的名称或进程ID。只使用最后定义的值。 
您还可以通过grep命令进行过滤。例如,执行com.eat application1进程的ps命令将如下所示: 
$ adb shell ps | grep com.eat 
USER PID PPID VSIZE RSS WCHAN PS NAME 
u0_a72 4257 144 320304 34540 ffffffff 00000000 S com.eat 
从这个输出中,我们可以提取com.eat应用程序的以下有趣的属性: 
•UID:u0_a72 
•PID:4257 
•PPID:144(父应用程序的进程号,在Android应用程序的情况下,始终是Zygote) 
检索进程和线程信息的另一种方法是使用DDMS2进行安装。 
我使用字符串EAT为本书中的应用程序创建一个命名空间。该字符串是本书标题的缩写。

All the threads that an application creates and starts are native Linux threads, a.k.a. pthreads, because they were defined in a POSIX standard. The threads belong to the process where they were created, and the parent of each thread is the process. Threads and processes are very much alike, with the difference between them coming in the sharing of resources. The process is an isolated execution of a program in a sandboxed environment compared to other processes, whereas the threads share the resources within a process. An important distinction between processes and threads is that pro‐ cesses don’t share address space with each other, but threads share the address space within a process. This memory sharing makes it a lot faster to communicate between threads than between processes, which require remote procedure calls that take up more overhead. Thread communication is covered in Chapter 4 and process communication in Chapter 5. 
When a process starts, a single thread is automatically created for that process. A process always contains at least one thread to handle its execution. In Android, the thread cre‐ ated automatically in a process is the one we’ve already seen as the UI thread. 
Let’s take a look at the threads created in a process for an Android application with the package name com.eat: 
$ adb shell ps -t | grep u0_a72 
USER PID PPID VSIZE RSS WCHAN PS NAME 
u0_a72 4257 144 320304 34540 ffffffff 00000000 S com.eat 
u0_a72 4259 4257 320304 34540 ffffffff 00000000 S GC 
u0_a72 4262 4257 320304 34540 ffffffff 00000000 S Signal Catcher 
u0_a72 4263 4257 320304 34540 ffffffff 00000000 S JDWP 
u0_a72 4264 4257 320304 34540 ffffffff 00000000 S Compiler 
u0_a72 4265 4257 320304 34540 ffffffff 00000000 S ReferenceQueueDemon 
u0_a72 4266 4257 320304 34540 ffffffff 00000000 S FinalizerDaemon 
u0_a72 4267 4257 320304 34540 ffffffff 00000000 S FinalizerWatchdogDaemon 
u0_a72 4268 4257 320304 34540 ffffffff 00000000 S Binder_1 
u0_a72 4269 4257 320304 34540 ffffffff 00000000 S Binder_2

应用程序创建和启动的所有线程都是本机的Linux线程又名并行线程,因为它们是在POSIX标准中定义的。线程属于创建它们的进程,每个线程的父进程都是进程。线程和进程非常相似,它们之间的区别在于共享资源。该过程是与其他进程相比,沙盒环境中的程序的独立执行,而线程共享进程中的资源。进程和线程之间的一个重要区别是进程之间不会共享地址空间,而是线程共享进程内的地址空间。这种内存共享使线程之间的通信速度比进程之间的速度要快得多,这些进程需要占用更多开销的远程过程调用。线程通信在第4章和第5章的过程通信中有所描述。 
当一个进程开始时,为该进程自动创建一个线程。一个进程总是包含至少一个线程来处理它的执行。在安卓中,在一个进程中自动创建的线程是我们已经看到的UI线程。 
让我们来看看一个Android的应用程序的进程中创建的线程,其中包含名为com.eat的包: 
$ adb shell ps -t | grep u0_a72 
USER PID PPID VSIZE RSS WCHAN PS NAME 
u0_a72 4257 144 320304 34540 ffffffff 00000000 S com.eat 
u0_a72 4259 4257 320304 34540 ffffffff 00000000 S GC 
u0_a72 4262 4257 320304 34540 ffffffff 00000000 S信号捕获器 
u0_a72 4263 4257 320304 34540 ffffffff 00000000 S JDWP 
u0_a72 4264 4257 320304 34540 ffffffff 00000000 S编译器 
u0_a72 4265 4257 320304 34540 ffffffff 00000000 S ReferenceQueueDemon 
u0_a72 4266 4257 320304 34540 ffffffff 00000000 S FinalizerDaemon 
u0_a72 4267 4257 320304 34540 ffffffff 00000000 S FinalizerWatchdogDaemon 
u0_a72 4268 4257 320304 34540 ffffffff 00000000 S Binder_1 
u0_a72 4269 4257 320304 34540 ffffffff 00000000 S Binder_2

On application start, no fewer than 10 threads are started in our process. The first thread —named com.eat—is started by default when the application launches. Hence, that is the UI thread of the application. All the other threads are spawned from the UI thread, which is seen on the parent process ID (PPID) of the other threads. Their PPID corre‐ sponds to the process ID (PID) of the UI thread.

在应用程序启动时,在我们的进程中启动不少于10个线程。 第一个线程名为com.eat - 在应用程序启动时默认启动。 因此,这是应用程序的UI线程。 所有其他线程都是从其他线程的父进程标识(PPID)中看到的UI线程生成的。 它们的PPID对应于UI线程的进程ID(PID)。 
Most of the threads are Dalvik internal threads, and we don’t have to worry about them from an application perspective. They handle garbage collection, debug connections, finalizers, etc. Let’s focus on the threads we need to pay attention to: 
u0_a72 4257 144 320304 34540 ffffffff 00000000 S com.eat 
u0_a72 4268 4257 320304 34540 ffffffff 00000000 S Binder_1 
u0_a72 4269 4257 320304 34540 ffffffff 00000000 S Binder_2

大多数线程是Dalvik内部线程,我们不必从应用程序角度来担心它们。 他们处理垃圾收集,调试连接,终结器等。让我们关注我们需要注意的线程: 
u0_a72 4257 144 320304 34540 ffffffff 00000000 S com.eat 
u0_a72 4268 4257 320304 34540 ffffffff 00000000 S Binder_1 
u0_a72 4269 4257 320304 34540 ffffffff 00000000 S Binder_2

Scheduling 
Linux treats threads and not processes as the fundamental unit for execution. Hence, scheduling on Android concerns threads and not processes. Scheduling allocates exe‐ cution time for threads on a processor. Each thread that is executing in an application is competing with all of the other threads in the application for execution time. The scheduler decides which thread should execute and for how long it should be allowed to execute before it picks a new thread to execute and a context switch occurs. A sched‐ uler picks the next thread to execute depending on some thread properties, which are different for each scheduler type, although the thread priority is the most important one. In Android, the application threads are scheduled by the standard scheduler in the Linux kernel and not by the Dalvik virtual machine. In practice, this means that the threads in our application are competing not only directly with each other for execution time, but also against all threads in all the other applications.

调度 
Linux将线程而不是进程作为执行的基本单位。因此,Android上的安排涉及到线程而不是进程。计划为处理器上的线程分配执行时间。在应用程序中执行的每个线程与应用程序中的所有其他线程竞争执行时间。调度程序决定哪个线程应该执行,以及在选择要执行的新线程之前应该允许执行多长时间,并发生上下文切换。线程优先级是最重要的一个线程,根据某些线程属性选择要执行的下一个线程,每个线程属性对于每个调度器类型是不同的。在Android中,应用程序线程由Linux内核中的标准调度程序调度,而不是由Dalvik虚拟机安排。实际上,这意味着我们的应用程序中的线程不仅直接竞争执行时间,而且还针对所有其他应用程序中的所有线程进行竞争。

The Linux kernel scheduler is known as a completely fair scheduler (CFS). It is “fair” in the sense that it tries to balance the execution of tasks not only based on the priority of the thread but also by tracking the amount of execution time3 that has been given to a thread. If a thread has previously had low access to the processor, it will be allowed to execute before higher-prioritized threads. If a thread doesn’t use the allocated time to execute, the CFS will ensure that the priority is lowered so that it will get less execution time in the future. 
The platform mainly has two ways of affecting the thread scheduling: 
Priority 
Change the Linux thread priority. 
Control group 
Change the Android-specific control group.

Linux内核调度程序被称为完全公平的调度程序(CFS)。 在这种意义上,它是“公平的”,它试图平衡任务的执行,不仅基于线程的优先级,而且还通过跟踪已经给线程的执行时间3。 如果线程以前对处理器的访问权限较低,则允许在更高优先级的线程之前执行。 如果线程不使用分配的时间执行,CFS将确保优先级降低,以便将来可以减少执行时间。 
该平台主要有两种影响线程调度的方式: 
优先 
更改Linux线程的优先级。 
控制组 
更改Android特定的控制组。

Priority 
All threads in an application are associated with a priority that indicates to the scheduler which thread it should allocate execution time to on every context switch. On Linux, the thread priority is called niceness or nice value, which basically is an indication of how nice a certain thread should behave toward other threads. Hence, a low niceness corresponds to a high priority. In Android, a Linux thread has niceness values in the range of -20 (most prioritized) to 19 (least prioritized), with a default niceness of 0. A thread inherits its priority from the thread where it is started and keeps it unless it’s explicitly changed by the application. 
An application can change priority of threads from two classes:

An application can change priority of threads from two classes: 
java.lang.Thread 
setPriority(int priority); 
Sets the new priority based on the Java priority values from 0 (least prioritized) to 
10 (most prioritized). 
android.os.Process 
Process.setThreadPriority(int priority); // Calling thread. Process.setThreadPriority(int threadId, int priority); // Thread with 
// specific id. 
Sets the new priority using Linux niceness, i.e. -20 to 19.

优先 
应用程序中的所有线程与优先级相关联,该优先级指示调度程序哪个线程应该在每个上下文切换上分配执行时间。在Linux上,线程优先级被称为优点或漂亮的值,这基本上表明某个线程应该对其他线程行为有多好。因此,低的优点对应于高优先级。在Android中,Linux线程具有-20(最优先级)到19(最优先级)的精确度值,默认值为0.线程从启动的线程继承其优先级,并保留它,除非它是由应用程序明确更改。 
应用程序可以从两个类更改线程的优先级:

应用程序可以从两个类更改线程的优先级: 
java.lang.Thread中 
setPriority(int priority); 
基于Java优先级值(从0(最小优先级)到)设置新的优先级 
10(最优先)。 
android.os.Process 
Process.setThreadPriority(int priority); //调用线程Process.setThreadPriority(int threadId,int priority); //线程与 
//具体ID。 
使用Linux的好处设置新的优先级,即-20到19。

Java Priority Versus Linux Niceness 
Thread.setPriority() is platform independent. It represents an abstraction of the underlying platform-specific thread priorities. The abstract priority values correspond to Linux niceness values according to the following table:

Java优先级与Linux的精确性 
Thread.setPriority()与平台无关。 它代表了基于平台的线程优先级的抽象。 抽象优先级值对应于Linux niceness值,如下表所示:


The mapping of Java priorities is an implementation detail and may vary depending on platform version. The niceness mapping values in the table are from Jelly Bean. 
Java优先级的映射是一个实现细节,可能会根据平台版本而有所不同。 表中的精美度映射值来自Jelly Bean。

Control groups 
Android not only relies on the regular Linux CFS for thread scheduling, but also imposes thread control groups4 on all threads. The thread control groups are Linux containers that are used to manage the allocation of processor time for all threads in one Container. All threads created in an application belong to one of the thread control groups. 
Android defines multiple control groups, but the most important ones for applications are the Foreground Group and Background Group. The Android platform defines ex‐ ecution constraints so that the threads in the different control groups are allocated different amounts of execution time on the processor. Threads in the Foreground Group are allocated a lot more execution time than threads in the Background Group,5 and Android utilizes this to ensure that visible applications on the screen get more processor allocation than applications that are not visible on the screen. The visibility on the screen relates to the process levels (see “The Linux Process and Threads” on page 31), as illus‐ trated in Figure 3-1. 
对照组 
Android不仅依赖于常规的Linux CFS进行线程调度,而且还对所有线程强加线程控制组4。线程控制组是Linux容器,用于管理一个容器中所有线程处理器时间的分配。在应用程序中创建的所有线程都属于其中一个线程控制组。 
Android定义了多个控制组,但最重要的应用程序是前台组和后台组。 Android平台定义了执行约束,以便在处理器上为不同控制组中的线程分配不同的执行时间。前台组中的线程比后台组中的线程分配了更多的执行时间,而且Android利用此功能可确保屏幕上的可见应用程序获得比在屏幕上不可见的应用程序更多的处理器分配。屏幕上的可见性与过程级别有关(请参见第31页的“Linux进程和线程”),如图3-1所示。

If an application runs at the Foreground or Visible process level, the threads created by that application will belong to the Foreground Group and receive most of the total processing time, while the remaining time will be divided among the threads in the other applications. A ps command issued on a foreground thread shows something like this (note the appearance of the fg group): 
adbshellps−P|grepu0a72u0a72425714432030434504fgffffffff00000000Scom.eatIftheusermovesanapplicationtothebackground,suchasbypressingtheHomebutton,allthethreadsinthatapplicationwillswitchthecontrolgrouptotheBack‐groundGroupandwillreceivelessprocessorallocation.psshowssomethinglike,withtheapplicationinthebggroup:4.cgroupsinLinux.5.ThethreadsintheBackgroundGroupcan′tgetmorethan 5−10如果应用程序在Foreground或Visible进程级别运行,该应用程序创建的线程将属于前台组,并接收大部分总处理时间,而剩余时间将在其他应用程序中的线程之间划分。在前台线程上发出的ps命令显示如下(注意fg组的外观):adb shell ps -P | grep u0_a72 
u0_a72 4257 144 320304 34504 fg ffffffff 00000000 S com.eat 
如果用户将应用程序移动到后台,例如通过按主页按钮,该应用程序中的所有线程将将控制组切换到后台组,并且将接收较少的处理器分配。 ps显示了与bg组中的应用程序相似的东西: 
Linux中的cgroups 
5.背景组中的线程总共不能超过约5-10%的执行时间。

$ adb shell ps -P | grep u0_a72 
u0_a72 4257 144 318700 32164 bg ffffffff 00000000 S com.eat 
When the application is seen on the screen again, the threads move back to the Fore‐ ground Group. This moving of threads between control groups is done as soon as the application become visible or invisible. The use of control groups increases the perfor‐ mance of the applications seen on the screen and reduces the risk of background ap‐ plications disturbing the applications actually seen by the user, hence improving the user experience. 
Although the control groups ensure that background applications interfere as little as possible with the performance of visible applications, an application can still create many threads that compete with the UI thread. The threads created by the application by default have the same priority and control group membership as the UI thread, so they compete on equal terms for processor allocation. Hence, an application that creates a lot of background threads may reduce the performance of the UI thread even though the intention is the opposite. To solve this, it’s possible to decouple background threads from the control group where the application threads execute by default. This decou‐ pling is ensured by setting the priority of the background threads low enough so that they always belong to the Background Group, even though the application is visible.

$ adb shell ps -P | grep u0_a72 
u0_a72 4257 144 318700 32164 bg ffffffff 00000000 S com.eat 
当再次在屏幕上看到应用程序时,线程将返回到前端组。一旦应用程序变得可见或不可见,就可以在控制组之间完成线程的移动。控制组的使用增加了屏幕上显示的应用程序的性能,并降低了背景应用程序的风险,从而影响用户实际看到的应用程序,从而改善了用户体验。 
虽然控制组确保后台应用程序尽可能少地干扰可见应用程序的性能,但应用程序仍然可以创建许多与UI线程竞争的线程。默认情况下,应用程序创建的线程与UI线程具有相同的优先级和控制组成员资格,因此它们以相等的条件竞争处理器分配。因此,创建大量后台线程的应用程序可能降低UI线程的性能,即使意图是相反的。为了解决这个问题,可以将后台线程与应用程序线程默认执行的控制组分离。通过将后台线程的优先级设置得足够低,使得它们始终属于背景组,即使应用程序可见,也可以确保这种解决方案。 
Lowering the priority of a thread with Process.setThreadPriori ty(Process.THREAD_PRIORITY_BACKGROUND) will not only reduce the priority but also ensure that this thread is decoupled from the pro‐ cess level of the application and always put in the Background Group.

使用Process.setThreadPriori ty(Process.THREAD_PRIORITY_BACKGROUND)降低线程的优先级不仅会降低优先级,还要确保该线程与应用程序的进程级别脱钩,并始终置于背景组中。

Summary 
All thread types in Android—UI, binder, and background—are Linux Posix threads. An application has a UI thread and binder threads when the process is started, but the application has to create background threads itself. All Android components execute on the UI thread by default, but long-running tasks should be executed on background threads to avoid slow UI rendering and the risk for ANRs. The UI thread is the most important thread, but it gets no special scheduling advantage compared to the other threads—the scheduler is unaware of which thread is the UI thread. Instead, it is up to the application to not let the background threads interfere more than necessary with the UI thread—typically by lowering the priority and letting the less important back‐ ground threads execute in the background control group.

概要 
Android-UI,binder和background中的所有线程类型都是Linux Posix线程。 应用程序在进程启动时具有UI线程和绑定线程,但应用程序必须自己创建后台线程。 默认情况下,所有Android组件都在UI线程上执行,但是长时间运行的任务应该在后台线程上执行,以避免用户界面渲染慢和ANR的风险。 UI线程是最重要的线程,但与其他线程相比,它没有特殊的调度优势 - 调度程序不知道哪个线程是UI线程。 相反,应用程序不要让后台线程与UI线程干扰更多,通常是通过降低优先级,并在后台控制组中执行不太重要的后台线程。

  • numerous 
    英 [‘njuːm(ə)rəs] 美 [‘numərəs] 
    adj. 许多的,很多的

  • bundled 
    v. 捆绑(bundle的过去分词);包;归拢;把…撵走 
    adj. 捆绑的;附带的

  • exposed 
    英 [ɪk’spəʊzd] 美 [ɪk’spozd] 
    adj. 暴露的,无掩蔽的 
    v. 暴露,揭露(expose的过去分词)

  • examining 英 美 [ɪg’zæmɪn] 
    v. 检查;审讯;进行考试(examine的ing形式) 
    adj. 审查的;考试的

  • hood 
    n. 头巾;覆盖;兜帽 
    vt. 罩上;以头巾覆盖

  • similarities 
    英 [sɪmə’lærətɪz] 美 [,sɪmə’lærətɪz] 
    类似 
    相似之处

  • coupling 
    英 [‘kʌplɪŋ] 美 [‘kʌplɪŋ] 
    n. [电] 耦合;结合,联结 
    v. 连接(couple的ing形式)

《Efficient Android Threading》Chapter 3---Threads on Android (Android中的线程)相关推荐

  1. android怎么关应用程序,如何关闭Android应用程序?

    Android有一个机制,以根据其文档安全地关闭应用程序.在退出的最后一个活动(通常是应用程序启动时首先出现的主要活动)中,只需在onDestroy()方法中放置几行.对System.runFinal ...

  2. Android主线程耗时动画卡顿,Android性能优化实战之界面卡顿

    原标题:Android性能优化实战之界面卡顿 作者:红橙Darren https://www.jianshu.com/p/18bb507d6e62 今天是个奇怪的日子,有三位同学找我,都是关于界面卡顿 ...

  3. Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析

    原文地址: http://blog.csdn.net/luoshengyang/article/details/6629298 在前面一篇文章浅谈Android系统进程间通信(IPC)机制Binder ...

  4. android 线程池 怎么用,android中的线程池 怎么用

    满意答案 qpierq0n5 2016.05.02 采纳率:52%    等级:13 已帮助:8164人 //在Android中实现线程池,首先需要实现一个线程工厂(ThreadFactory)的子类 ...

  5. android aar项目_一文了解Android游戏SDK开发

    去年从平安离职之后,加入了一家游戏公司,负责游戏SDK相关的业务开发和维护工作,经过半年来的摸索,对于游戏SDK的开发有了一定的理解,下面就对游戏SDK开发涉及到的知识点进行简单的梳理. SDK SD ...

  6. Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析(1)

    在前面一篇文章浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路中,介绍了在Android系统中Binder进程间通信机 ...

  7. 【Android开发那点破事】解决android.os.NetworkOnMainThreadException

    昨天和女朋友换了手机,我的iPhone 4S 换了她得三星I9003.第一感觉就是好卡,果断刷机.以前是Android 2.3的系统.回来刷成了4.4. 好了,问题来了.在我用手机测试我们的APP的时 ...

  8. Android开发中的线程池使用

    一.前言 既然Android中已经有了线程的概念,那么为什么需要使用线程池呢?我们从两个方面给出使用线程池的原因. 首先线程的新建和销毁都是存在性能上的消耗的,如果一个时间段有大量的网络请求,那么就需 ...

  9. Android监听左右滑删除通知,Android 滑动监听RecyclerView线性流+左右划删除+上下移动...

    废话不多说了,直接给大家贴代码了.具体代码如下所示: xmlns:tools="http://schemas.android.com/tools" android:layout_w ...

  10. ios android安全性分析,Android与iOS的对比分析及Android安全技术的设计与实现

    摘要: 近年来科技的发展和进步极大的推动了智能手机的飞速发展,手机功能的日益强大使人们对其依赖度显著上升.作为与人们生活密不可分通讯工具,手机安全的重要性不言而喻.现如今,随着手机网络的迅猛发展和形形 ...

最新文章

  1. 密码技术--国密SM4分组密码算法及Go语言应用
  2. 常用的设计模式——观察者设计模式?和发布者-订阅者设计模式的区别
  3. Dockerfile----ubuntu-java
  4. Oracle 行列转换
  5. python中dtype什么意思_什么是dtype('O')?
  6. 年薪百万程序员竟遭亲妈拍卖:才拍到10块,还不够买一盒鸡蛋!
  7. 电容触摸按键实验(STM32F407)
  8. swfupload ajax,swfupload ajax无刷新上传图片实例代码
  9. 蓝桥杯2019B组 C++
  10. 梅捷512G固态拆机+得一微YS9082HP量产教程+YS9082HP开卡工具
  11. ajax带参数get,使用jQuery ajax方法传递GET参数
  12. Oracle Temp临时表空间及其故障处理
  13. ORACLE WITH与性能优化
  14. CDH6中的各种目录
  15. 最全的PDF转换成Word方法,搞定市面上99%的PDF
  16. cross-entropy for one-stage detecor
  17. 什么是C和C++标准库?
  18. 视音频数据处理入门:H.264视频码流解析
  19. 点云深度学习的经典理论与实用算法
  20. 生态系统服务(InVEST模型)土壤保持、水源涵养、氮磷输出、生态保护、生物多样性、碳固

热门文章

  1. 北航计算机考研录取多少人,北航计算机考研近三年报考录取情况
  2. 最新二次开发仿包图网素材图片源码
  3. 基于Linux利用PPP实现4G模块联网
  4. 微信小程序商店:极乐小程序商店推荐之601~700
  5. 深度学习入门(看了就会)
  6. window7下visio 2013 64位激活工具
  7. 虚拟机安装win10未找到驱动程序
  8. 题5 正确的Java垃圾回收说法
  9. python gif压缩_基于python压缩gif图片大小。
  10. 模电、数电、电力电子、开关电源基础知识总结