Google Android官方文档进程与线程(Processes and Threads)翻译

时间:2021-12-29 17:33:04

android的多线程在开发中已经有使用过了,想再系统地学习一下,找到了android的官方文档,介绍进程与线程的介绍,试着翻译一下。

原文地址:http://developer.android.com/guide/components/processes-and-threads.html

首先翻译一下GOOGLE的官方文档,

Processes and Threads
When an application component starts and the application does not have any other components running,
the Android system starts a new Linux process for the application with a single thread of execution.
(当一个应用的组件开始运行,并且这个应用也没有其他组件在运行,那么android系统会为这个应用启动一个新的linux进程和单一的线程去运行)
By default, all components of the same application run in the same process and thread (called the "main" thread). 
默认的话,同一个应用的所有组件都运行在同一个进程和线程中(叫做“主线程”)
If an application component starts and there already exists a process for that application (because another component from the application exists), then the component is started within that process and uses the same thread of execution.
(如果这个应用的组件启动,且这个应用的进程已经存在了(因为这个应用的其他组件已经运行了),那么这个组件会在已经存在的进程里使用同一个进程运行)
However, you can arrange for different components in your application to run in separate processes, and you can create additional threads for any process.(但是,你也可以为同一个应用的不同组件指定不一样的进程,你可以为任何进程创建其他的线程)

 

Processes
By default, all components of the same application run in the same process and most applications should not change this. However, if you find that you need to control which process a certain component belongs to, you can do so in the manifest file.默认的话,同一个应用的所有组件都运行在同一个进程中,并且大部分的应用都不应该更改这个行为。但是,如果你需要控制具体的某个组件运行在具体的线程中,
你也可以在manifest文件中去指定The manifest entry for each type of component element—
<activity>, <service>, <receiver>, and <provider>—supports an android:process attribute that can specify a process in which that component should run.
在manifest文件中,<activity>,<service>,<receiver>,<provider>可以在这些组件的android:process属性中指定其要运行的进程
You can set this attribute so that each component runs in its own process or so that some components share a process while others do not.
你可以设置这个属性,使各个组件运行在它们自己的进程中,或者使一些组件共享同一个进程,一些组件没有。
You can also set android:process so that components of different applications run in the same process—provided that the applications share the same Linux user ID and are signed with the same certificates.
你也可以设置这个属性,使不同应用的组件运行在同一个进程中,使这些应用可以共享相同的linux user ID, 签上同样的证书The
<application> element also supports an android:process attribute, to set a default value that applies to all components.
<application>这个元素也支持android:process这个属性,在这里元素里设置这个属性值的话,会成为这个应用所有组件的默认值
Android might decide to shut down a process at some point, when memory is low and required by other processes that are more immediately serving the user.
Android有可以在某些时差停止一个进程,比如当内存很小且被其它正在为用户服务的进程请求时。
Application components running in the process that's killed are consequently destroyed. A process is started again for those components when there's again work for them to do.当进程被杀时,运行在这个进程上的组件也会被销毁。如果那些组件有事情再做时,线程会再次启动。
When deciding which processes to kill, the Android system weighs their relative importance to the user.
系统决定杀哪个进程时,会衡量它们对用户的重要性。
For example, it more readily shuts down a process hosting activities that are no longer visible on screen, compared to a process hosting visible activities.
比如说,相对于那些持有可视activity的进程,那些持有不可视activity的进程会更容易被杀掉
The decision whether to terminate a process, therefore, depends on the state of the components running in that process.
所以,决定一个线程是否被杀,是依据在这个进程上运行的组件的状态上的。
The rules used to decide which processes to terminate is discussed below.
下面会讨论“哪个线程会被终止”的一些规则

 

Process lifecycle

The Android system tries to maintain an application process for as long as possible, but eventually needs to remove old processes to reclaim memory for new or more important processes.
Android系统会尽可能地维护一个应用的进程,但是为了给新的或者更重要进程提供内存而终止老的进程
To determine which processes to keep and which to kill, the system places each process into an "importance hierarchy" based on the components running in the process and the state of those components.
android系统提供了一个“重要等级”来决定哪些线程是可以被终止的。这个“重要等级”是根据这个进程上运行的组件和这个组件的状态来划分的。

Processes with the lowest importance are eliminated first, then those with the next lowest importance, and so on, as necessary to recover system resources.
当需要恢复系统资源时,重要性越小的进程就会更早地被终止
There are five levels in the importance hierarchy. The following list presents the different types of processes in order of importance (the first process is most important and is killed last):“重要等级”有5个等级,下面的列表列出了不同进程重要性的顺序。排第一的进程是最重要的,也是最后被终止的。
(Foreground process > Visible process > Service process > Background process > Empty process)Foreground process
A process that is required for what the user is currently doing. A process is considered to be in the foreground if any of the following conditions are true:
一个进程,如果下面任何一个条件成立,就算是一个foreground 进程It hosts an Activity that the user is interacting with (the Activity's onResume() method has been called).
它持有一个和用户交互的activity(activity的 onResume()方法已经被调用)It hosts a Service that's bound to the activity that the user is interacting with.
它持有一个service,这个service和一个正在和用户交互的activity绑定It hosts a Service that's running "in the foreground"—the service has called startForeground().
它持有一个serverce,这个service运行在foreground,即这个service调用了startForeground()方法
It hosts a Service that's executing one of its lifecycle callbacks (onCreate(), onStart(), or onDestroy()).
它持有一个service,这个service正在行任何一个生命周期的回调,比如onCreate(),onStart()或者onDestroy()It hosts a BroadcastReceiver that's executing its onReceive() method.
它持有一个BroadcastReceiver,它正在执行onReceive()方法Generally, only a few foreground processes exist at any given time.
一般来说,在给定的时刻只有很少的前台里程存在
They are killed only as a last resort—if memory is so low that they cannot all continue to run.
它们只有在内存很少,导致它们不能运行时,才会被终止
Generally, at that point, the device has reached a memory paging state, so killing some foreground processes is required to keep the user interface responsive.
一般来说,在某种情况下,设备达到一个memory paging state, 为了使用户界面有响应,这时才需要终止这个前台进程Visible process
A process that doesn't have any foreground components, but still can affect what the user sees on screen.
一个进程,如果没有前台组件,但是仍然影响着屏幕的显示(即用户所看到的东西),那么这个进程就是可视进程
A process is considered to be visible if either of the following conditions are true:
一个进程,如果下面的任何一个条件成立,则被认为是可视进程It hosts an Activity that is not in the foreground, but is still visible to the user (its onPause() method has been called).
它持有一个非前台的activity, 但是对用户仍然可视(onPause()方法已经被调用)
This might occur, for example, if the foreground activity started a dialog, which allows the previous activity to be seen behind it.
比如,这种情况发生在一个前台activity启动了一个对话框,而之前这个activity在dialog后面,用户可以见到。It hosts a Service that's bound to a visible (or foreground) activity.
它持有一个service,这个service和一个可视或者前台的activity绑定A visible process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.
一个可视进程被认为是很重要的,它是不会被终止的,除非终止它是为了保持前台进程可运行Service process
A process that is running a service that has been started with the startService() method and does not fall into either of the two higher categories.
一个进程,如果运行着一个service且调用了startService()方法,并且不属于上面两个更高的分类,那么这个进程就是服务进程
Although service processes are not directly tied to anything the user sees, they are generally doing things that the user cares about (such as playing music in the background or downloading data on the network), so the system keeps them running unless there's not enough memory to retain them along with all foreground and visible processes.
虽然服务进程不会和用户看到的东西直接绑定在一起,但是它们一般都在做一些用户关心的事情,比如在后台播放音乐或者下载数据。所在只有在内存不足以使它和前台服务与后台服务一起运行时才会终止服务进程

Background processA process holding an activity that's not currently visible to the user (the activity's onStop() method has been called).
一个进程持有的activity是不可视的,这个activity的onStop()方法已经被调用过
These processes have no direct impact on the user experience, and the system can kill them at any time to reclaim memory for a foreground, visible, or service process.
这些进程对用户体验没有直接的影响,所以系统可以在任何时候终止这个进程来给前台进程,可视进程和服务进程分配内存
Usually there are many background processes running, so they are kept in an LRU (least recently used) list to ensure that the process with the activity that was most recently seen by the user is the last to be killed.
通常来说,有很多后台进程在运行,所以这些进程被保存在LRU列表中(最新最近被使用),来保证那些最近被用户看到的activity最后被杀掉。
If an activity implements its lifecycle methods correctly, and saves its current state, killing its process will not have a visible effect on the user experience, because when the user navigates back to the activity, the activity restores all of its visible state. See the Activities document for information about saving and restoring state.
如果一个activity的生命周期方法被正确地实现,且保存了这个activity的state, 杀掉这个进程没有用户体验上的影响。因为当用户返回这个activity的时候,这个activity会恢复所有之前可视的state。 这方面可以看activity关于保存和恢复state的文档
Empty process
A process that doesn't hold any active application components.
空进程:没有持有任何活跃的应用组件
The only reason to keep this kind of process alive is for caching purposes, to improve startup time the next time a component needs to run in it. The system often kills these processes in order to balance overall system resources between process caches and the underlying kernel caches.
保存空进程的唯一原因是为了缓存。为了减少下一个在这个进程上运行的组件的启动时间。为了平衡系统缓存和底部内核的缓存之间的系统资源,系统常常会杀掉这些进程。Android ranks a process at the highest level it can, based upon the importance of the components currently active in the process.
Android会根据这个进程上活跃的组件的重要性,把一个进程排在它能达到的最高的级别上。
For example, if a process hosts a service and a visible activity, the process is ranked as a visible process, not a service process.比如,如果一个进程持有一个service和一个可视activity,这个进程会被认为是一个可视进程,而不是一个服务进程
In addition, a process's ranking might be increased because other processes are dependent on it—a process that is serving another process can never be ranked lower than the process it is serving.
除此之外,一个进程的排行有可能因为其他进程的依赖而增加。一个进程如果为其它进程服务,它的级别是不能低于它服务的进程的。
For example, if a content provider in process A is serving a client in process B, or if a service in process A is bound to a component in process B, process A is always considered at least as important as process B.比如一个content provider在进程A,服务着一个在进程B的客户,或者一个在进程A的service绑定在一个进程B上的组件,A总是会被认为至少和B进程一样重要的。
Because a process running a service is ranked higher than a process with background activities, an activity that initiates a long-running operation might do well to start a service for that operation, rather than simply create a worker thread—particularly if the operation will likely outlast the activity. For example, an activity that's uploading a picture to a web site should start a service to perform the upload so that the upload can continue in the background even if the user leaves the activity. Using a service guarantees that the operation will have at least "service process" priority, regardless of what happens to the activity. This is the same reason that broadcast receivers should employ services rather than simply put time-consuming operations in a thread.
因为一个服务进程的级别比后台进程高,一个activity如果要做一个耗时的操作,更好的办法是为这个操作启动一个服务,而不在简单地创建一个worker thread特别是如果这个操作有可能 比activity还要久的时候比如,当一个activity在上传一张图片的时候,应该启动一个服务来做上传操作,所以即使用户离开这个activity,上传也可以在后台继续使用一个服务可以保证这个操作最少拥有“服务进程”的优先级,而不用去管这个activity发生了什么这也是brocast receivers 应该使用service而不是仅仅在一个线程中做耗时操作

 

 

Threads

When an application is launched, the system creates a thread of execution for the application, called "main." 
当一个应用运行时,系统会为这个应用创建一个线程,称为“主线程”
This thread is very important because it is in charge of dispatching events to the appropriate user interface widgets, including drawing events.
这个线程很重要,因为它控制着用户交互时事件的分发,包括“画”事件
It is also the thread in which your application interacts with components from the Android UI toolkit (components from the android.widget and android.view packages). As such, the main thread is also sometimes called the UI thread.这个线程也是你的应用和一些来自Android UI toolkit的组件交互的线程(这些组件来自android.widget和android.view 包)。 也因此,这个主线程有时候也叫做UI线程

The system does not create a separate thread for each instance of a component.
系统没有为组件的实例分别创建线程
All components that run in the same process are instantiated in the UI thread, and system calls to each component are dispatched from that thread. Consequently, methods that respond to system callbacks (such as onKeyDown() to report user actions or a lifecycle callback method) always run in the UI thread of the process.所有在同一个进程里运行的组件都是在UI线程里实例化的,系统调用组件是在这个线程里分发的。因此,一些属于系统回调的方法(比如onKeyDown(),或者生命周期的回调方法)总是运行在这个进程的UI进程里

For instance, when the user touches a button on the screen, your app's UI thread dispatches the touch event to the widget, which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget that it should redraw itself.
比如,当用户点击屏幕时,你应用的UI线程会分发点击事件给组件,进而会设置它的点击状态(pressed state)然后给事件队列发送一个“无效”的请求(invalidate request). 这个UI线程会从事件队列里弹出这个请求,然后通知这个组件重画自己

When your app performs intensive work in response to user interaction, this single thread model can yield poor performance unless you implement your application properly.
除非你正确地实现了你的应用,否则,当你的应用与用户交互时,在这个线程里执行一些很繁重的工作,这个线程的性能会变得很差
Specifically, if everything is happening in the UI thread, performing long operations such as network access or database queries will block the whole UI.
特别地,如果所有的事情都在UI线程里做,做一些耗时的操作,比如连接网络,或者做数据库查询,这些都会阻塞UI线程
When the thread is blocked, no events can be dispatched, including drawing events. From the user's perspective, the application appears to hang. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog. The user might then decide to quit your application and uninstall it if they are unhappy.当线程被阻塞时,事件不会被分发,包括“画”事件。从用户的角度来看,这个应用卡住了。更糟糕的是,如果这个UI线程被阻塞超过5秒,应用会弹出ANR(应用不响应)窗口。用以有可能因此退出或者卸载你的应用

Additionally, the Andoid UI toolkit is not thread-safe. So, you must not manipulate your UI from a worker thread—you must do all manipulation to your user interface from the UI thread. Thus, there are simply two rules to Android's single thread model:
还有,Android UI toolkit不是线程安全的,所以,你肯定不可以工作线程(worker thread)中更新你的UI,你必须在UI线程里更新你的UI。因此,Android的单线程模型有两个规则:

Do not block the UI thread
不要阻塞UI线程Do not access the Android UI toolkit from outside the UI thread
不要在UI线程之外操作与UI相关的API(或者说更新UI)

 

Worker threads

Because of the single thread model described above, it's vital to the responsiveness of your application's UI that you do not block the UI thread. 
根据上面描述的单线程模型,不阻塞UI线程对应用的响应来说是很重要的
If you have operations to perform that are not instantaneous, you should make sure to do them in separate threads ("background" or "worker" threads).如果你有操作不是短时间内可以完成的,你应该在不同的线程中执行一些操作,比如后台线程,工作线程,而不是在UI线程里操作
For example, below is some code for a click listener that downloads an image from a separate thread and displays it in an ImageView:
比如,下面的代码就是在其他线程里下载图片然后把它显示在ImageView里
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork("http://example.com/image.png");
mImageView.setImageBitmap(b);
}
}).start();
}
At first, this seems to work fine, because it creates a new thread to handle the network operation. However, it violates the second rule of the single-threaded model: do not access the Android UI toolkit from outside the UI thread—this sample modifies the ImageView from the worker thread instead of the UI thread. This can result in undefined and unexpected behavior, which can be difficult and time-consuming to track down.
一开始,这个代码看起来好像是正确的,因为它创建了一个新的去执行网络操作。当时,它破坏了单线程模型的第二条规则:不要在UI线程之后调用UI的api。这个例子在worker thread里面改变了ImageView而不是在UI线程里改变。
这会导致出现一些没定义的或者不是我们期望的行为,使我们很难且很费时地去查找这些错误
To fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:
安卓了提供了几种方法,从其他线程操作UI线程,来解决上面出现的问题。下面列出了一些解决方法
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)

For example, you can fix the above code by using the View.post(Runnable) method:

public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
})
;
}
}).start();
}
Now this implementation is thread-safe: the network operation is done from a separate thread while the ImageView is manipulated from the UI thread.
现在这个实现是线程安全的,网络操作在另一个线程中执行的,而ImageView的更改是在UI线程里
However, as the complexity of the operation grows, this kind of code can get complicated and difficult to maintain.
然后,随着我们的操作越来越复杂,这一类型的代码会变得越来越复杂,难以维护
To handle more complex interactions with a worker thread, you might consider using a Handler in your worker thread, to process messages delivered from the UI thread. Perhaps the best solution, though, is to extend the AsyncTask class, which simplifies the execution of worker thread tasks that need to interact with the UI.
如果要在worker thread里处理复杂的交互,你应该考虑在worker thread里面使用handler去处理从UI thread里传来的信息。也许,最好的办法就是继承AsyncTask类,它简化了worker thread与UI交互的执行

 

Using AsyncTask

AsyncTask allows you to perform asynchronous work on your user interface. It performs the blocking operations in a worker thread and then publishes the results on the UI thread, without requiring you to handle threads and/or handlers yourself.
AsyncTask允许你在用户界面执行异步操作。它在worker thread里面执行阻塞操作,然后可以把结果通知到UI thread上,而你自己不需要处理线程和handler
To use it, you must subclass AsyncTask and implement the doInBackground() callback method, which runs in a pool of background threads. To update your UI, you should implement onPostExecute(), which delivers the result from doInBackground() and runs in the UI thread, so you can safely update your UI. You can then run the task by calling execute() from the UI thread.
使用AsyncTask必须继承它,并且实现doInBackgroud()方法,这个方法运行在backgroud threads的池里。要更新UI,你需要实现onPostExecute(),它会把doInBackground的结果运行在UI thread里,因此你可以安全地更新UI。你可以调用execute()方法来运行这个线程。
For example, you can implement the previous example using AsyncTask this way:
比如,你可以使用AsyncTask实现前面提到的例子:
public void onClick(View v) {
new DownloadImageTask().execute("http://example.com/image.png");
}

private class DownloadImageTask extends AsyncTask
<String, Void, Bitmap> {
/** The system calls this to perform work in a worker thread and
* delivers it the parameters given to AsyncTask.execute() */
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}

/** The system calls this to perform work in the UI thread and delivers
* the result from doInBackground() */
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
}
}
Now the UI is safe and the code is simpler, because it separates the work into the part that should be done on a worker thread and the part that should be done on the UI thread.
现在,这个UI是安全的,代码也简单了很多。因为它把需要在worker thread和ui thread里做的工作分开了
You should read the AsyncTask reference for a full understanding on how to use this class, but here is a quick overview of how it works:
你想要完整地理解AsyncTask,应该去读它的文档,这里只是简单说明它是怎么工作的
You can specify the type of the parameters, the progress values, and the final value of the task, using generics
通过泛型,你可以指定参数的类型,过程的值,结果的值The method doInBackground() executes automatically on a worker thread
doInBackground()这个方法自动地在worker thread里面运行onPreExecute(), onPostExecute(), and onProgressUpdate() are all invoked on the UI thread
onPreExecute(), onPostExecute(), 和 onProgressUpdate()都是在UI线程里面调用的The value returned by doInBackground() is sent to onPostExecute()
doInBackground()返回的值会传递到onPostExecute()里You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread
你也可以任何时候在doInBackground()里面调用publishProgress(),从而会在ui线程里执行onProgressUpdate();You can cancel the task at any time, from any thread
你也可以在任何时候,从任何线程里取消这个异步的task
Caution: Another problem you might encounter when using a worker thread is unexpected restarts in your activity due to a runtime configuration change (such as when the user changes the screen orientation), which may destroy your worker thread. To see how you can persist your task during one of these restarts and how to properly cancel the task when the activity is destroyed, see the source code for the Shelves sample application.
注意:有一个问题你在使用worker thread会遇到的情况就是,当你的activity因为一些运行时配置的改变而重启时(比如当用户改变屏幕的方向),有可能会销毁worker thread. 想要知道怎么在activity restart的时候保持你的线程,或者知道在activity销毁时,如何正确地取消这个线程,请参见Shelves(注:一个Android书架管理应用程序,项目主页在http://code.google.com/p/shelves/)示例应用程序的源代码。

 

Thread-safe methods

In some situations, the methods you implement might be called from more than one thread, and therefore must be written to be thread-safe.
在某些情况下,你实现的方法有可能被多个线程调用,因这个方法必须被写成线程安全的。
This is primarily true for methods that can be called remotely—such as methods in a bound service.
对于能被远程调用的方法,比如绑定服务,这是正确的。
When a call on a method implemented in an IBinder originates in the same process in which the IBinder is running, the method is executed in the caller's thread.

However, when the call originates in another process, the method is executed in a thread chosen from a pool of threads that the system maintains in the same process as the IBinder (it's not executed in the UI thread of the process). For example, whereas a service's onBind() method would be called from the UI thread of the service's process, methods implemented in the object that onBind() returns (for example, a subclass that implements RPC methods) would be called from threads in the pool. Because a service can have more than one client, more than one pool thread can engage the same IBinder method at the same time. IBinder methods must, therefore, be implemented to be thread-safe.
Similarly, a content provider can receive data requests that originate in other processes. Although the ContentResolver and ContentProvider classes hide the details of how the interprocess communication is managed, ContentProvider methods that respond to those requests—the methods query(), insert(), delete(), update(), and getType()—are called from a pool of threads in the content provider's process, not the UI thread for the process. Because these methods might be called from any number of threads at the same time, they too must be implemented to be thread-safe.

Interprocess Communication(进程间通信)

Android offers a mechanism for interprocess communication (IPC) using remote procedure calls (RPCs), in which a method is called by an activity or other application component, but executed remotely (in another process), with any result returned back to the caller. This entails decomposing a method call and its data to a level the operating system can understand, transmitting it from the local process and address space to the remote process and address space, then reassembling and reenacting the call there. Return values are then transmitted in the opposite direction. Android provides all the code to perform these IPC transactions, so you can focus on defining and implementing the RPC programming interface.

To perform IPC, your application must bind to a service, using bindService(). For more information, see the Services developer guide.