您的位置:首页 > 移动开发 > Android开发

Android开发文档标准翻译(01)一Processes and Threads

2014-09-05 14:22 651 查看

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. 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.

当一个应用组件开始并且这个应用不含有任何其它的组件在运行时,Android系统为这个应用开始启动一个新的Linux进程和一个单一的执行线程。默认情况下,同一个应用的所有组件运行在相同的进程和线程中(叫做主线程)。如果一个应用组件开始并且这应用进程已经存z在(因为其它组件来自这个应用存在的线程),所以组件开始在进程内并且使用同样的执行线程。然而,你可以在你的应用中把不同组件运行在不同进程中,并且你可以在任何进程创建额外的线程。

This document discusses how processes and threads work in an Android application.

这个文档考论进程和线程在Android应用中是怎样工作的。

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. 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.

这个manifest入口有每一个组件元素的类型-<activity>,<service>,<receiver>,and<provider>-这个组件支持一个android:process属性,这个属性会指定组件应该运行在哪个进程中。如果你设置这个了属性所以每一个组件运行在它自检的进程中或者一些组件共享一个进程而其它的进程不可以。你也可以设置android:process属性使得不同的应用组件运行在同一个相同进程为这个应用进程提供共享在相同Linux用户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. 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.

Android可能在某一刻决定去关闭进程,当内存低和需要通过其它进程去立即服务用户的时候。运行的进程被系统杀死应用组件也会立即销毁。当有工作再次需要他们去做的时候,那些组件所在的进程会重新开始。

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.
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.

当什么时候决定去杀死进程,Android系统会衡量组件对用户相对重要性,例如,相比一个活跃的可视活动而言它更乐意关闭一个不在屏幕上长时间可见的活跃活动。决定某个线程被杀死,因此,是依赖于运行在线程组件的状态.考论决定线程被终止使用下面规则。

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.
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. Processes with the lowest importance are eliminated first,
then those with the next lowest importance, and so on, as necessary to recover system resources.

Android系统试图尽可能长时间的去保持一个应用进程,但是最终会移除老的进程为一个新的或者更多重要的进程去回收内存。去决定进程是保持还是被杀死,系统里的每个进程进入"重要等级"中,基于进程中运行的组件和这些组件的状态。如果必要去恢复系统资源,重要性低的线程首先会被排除,然后下一个重要性低会被排除。

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):

有五个重要等级级别。下面列表列出了按重要性顺序不同类型的进程(首先最重要的进程应该最后被杀死)。

一、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:

当前用户正在需要的进程。如果下面的任何一个条件都成立,这个进程被认为是前台进程。

1.It hosts an Activity that the user is interacting with (the Activity's onResume() method has been called).

2.It hosts a Service that's bound to the activity that the user is interacting with.

3.It hosts a Service that's running "in the foreground"—the service has called startForeground().

4.It hosts a Service that's executing one of its lifecycle callbacks (onCreate(), onStart(), or onDestroy()).

5.It hosts a BroadcastReceiver that's executing its onReceive() method.

1.它是一个正在与用户交互的Activity的宿主进程(这个Activity的onResume()方法将被调用)

2.它是一个绑定到正在与用户交互的Activity的服务宿主进程。

3.它是一个运行在前台的服务宿主进程-service的startForeground()方法已经被调用

4.它是一个正在执行自己的生命周期回调方法(onCreate(),onStart(),或者 onDestroy())的服务宿主进程

5.它是一个正在执行的它自己的onReceive()方法的BroadcastReceiver宿主进程

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.

一般来说,只有一些前台进程存在任何时刻.如果内存低导致他们不能正常运行。他们才会最后被杀死.通常来说,在那时,设备到达一个内存分页状态,因此会杀死一些前台进程需要去保持用户界面响应。

二、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:

一个进程没有任何前台组件,但是仍然会影响用户在屏幕可视.如果下面其中一个条件满足则就这个进程被认为是可视的。

1.It hosts an Activity that is not in the foreground, but is still visible to the user (its onPause() method has been called). This might occur, for example, if the foreground activity started a dialog, which allows the previous activity to be seen behind it.

2.It hosts a Service that's bound to a visible (or foreground) activity.

1.它是一个没有在前台但是仍然对用户来说仍然可见的Activity宿主进程(它的onPause()方法被调用)。这可能发生,例如,如果前台activity开始一个dialog,允许前面的Activity在它的后面可见

2.它是一个绑定到可视(或者是前台)的Activity的服务宿主进程

A visible process is considered extremely important and will not be killed unless doing so is required to keep all foreground processes running.

一个可视进程被认为是非常重要的并且不会被杀死除非需要保持所有的前台进程运行。

四、Background process(后台进程)

A process holding an activity that's not currently visible to the user (the activity's onStop() method has been called). 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. 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的onStop()方法被调用).这些进程不会直接影响用户体验,并且系统会在任何时候为前台,可视,或者服务进程回收内存去杀死他们。通常有很多后台进程运行,所以他们是保存在LRU(Least recently used)列表中确保通过用户最近看见的Activity的进程最后被杀死。如果一个Activity正常实现它的生命周期方法,并且保存它的状态.杀死这个进程在用户可视体验上不会影响,因为当用户返回Activity的时候,这个Activity会重新恢复他多有的可视状态。看有关于保存和恢复状态信息的文档。

五、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. For example, if a process hosts a service and a visible
activity, the process is ranked as a visible process, not a service process.

Android它会基于在进程中当前活跃组件的重要行排在最高的级别上。例如,一个进程持有一个服务和可视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.

此外,进程划分的级别可能会增加因为其它的进程是依赖于它--一个进程服务于其它进程,这个进程从不会被划分为低等级甚至超过它服务的进程。例如,如果在进程A的content provider服务进程B的客户端,或者如果在A进程中的服务绑定到进程B的组件。那么进程总是至少被认为和进程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为这个操作启动一个服务更好,而不是简单去创建一个工作线程。特别是如果这个操作在activity可能比较耗时。例如,一个上传一张图片到网站的Aciticity应该启动一个服务执行上传,即使用户离开这个Activity在后台依然执行上传。使用一个服务保证这个操作至少有“服务进程”优先级,而不用去知道这个Activity发生了什么.同样的道理broadcast receivers应该使用serive而你不简单的在线程中放耗时的操作。

Thread(线程)

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 and 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.

系统没有为每一个组件的实例分别创建线程,运行在同一个线程中所有组件在UT线程中实例化,并且系统调用每个组件去分发是来自这个线程。所以,响应系统回调的方法(例如 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.

例如,当用户在屏幕上触摸一个按钮,你的app的UI线程为这个组件分发触摸事件,然后会设置它的点击状态和给事件队列中返回一个无效的请求。这个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. 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线程中发生,执行长时间操作如一个网络请求或者数据查询将阻塞所有的UI。当现成被阻塞时,没有事件会被分发,包括绘制事件。从用户角度来看,这个应用出现卡屏。更糟糕的是,如果UI线程被阻塞超过几秒(大约现在的五秒)用户界面会弹出很差的"应用没有想要"(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不是线程安全的。所以你肯定不能在工作线程操作你的UI--你用户界面做所有的操作必须在UI线程中执行。因此,Android单线程模式有两个简单的规则。

*1.Do not block the UI thread

*2.Do not access the Android UI toolkit from outside the UI thread

1.不能阻塞UI线程

2.除UI线程其它的线程不能访问Android UI toolkit

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. 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:

例如,以下是点击监听器从一个单独的线程下载图片并且显示图片的一些代码。



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线程以外的线程不能访问Android UI

toolki-这个例子在是工作线程中修改而不是在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:

去解决这个问题。Android提供几个方法从其它其它线程去访问UI线程。这里列出了一些帮助的方法。

1.Activity.runOnUiThread(Runnable)

2.View.post(Runnable)

3.View.postDelayed(Runnable, long)

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

例如,你可以通过使用View.post(Runnable)方法解决上面代码。



Now this implementation is thread-safe: the network operation is done from a separate thread while the ImageView is manipulated from the UI thread.

现在这个实现是线程安全的:这个网络操作来自分开的线程去执行,操作这个图片的是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.

然而,当这操作增加时会变得复杂,这类代码会变得复杂并且难以维护。在工作线程中去执行更多的复杂交互,你可能考虑在你的工作线程使用Handler处理从UI线程中传来的信息。或许最好的解决办法是继承AsynTask类,它简化了工作线程需要和UI交互任务的执行。

Using AsyncTask(使用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允许在你的用户界面中执行异步工作。它在一个工作线程中执行阻塞操作然后通知结果到UI线程,不需要你去处理线程或者你的handlers。

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子类实现doInBackground()回调方法,这个方法运行在后台线程池中。去更新你的UI,你应该实现onPostExecute();他会把doInBackground()的结果传送到运行的UI线程中。所以你会安全的更新你的UI。你可以从UI线程通过调用execute()运行当时的任务。

For example, you can implement the previous example using AsyncTask this way:

例如,你可以使用AsyncTask类这个方法实现先前的例子。



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是安全并且代码简单,因为工作线程中应该做的部分工作和UI线程应该做的部分工作是分开的。

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引用,完全理解这个类怎么去使用,不过这里是快速学习他是怎么工作的。

1.You can specify the type of the parameters, the progress values, and the final value of the task, using generics

2.The method doInBackground() executes automatically on a worker thread

3.onPreExecute(), onPostExecute(), and onProgressUpdate() are all invoked on the UI thread

4.The value returned by doInBackground() is sent to onPostExecute()

5.You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread

6.You can cancel the task at any time, from any thread

1.使用泛型,你会只能指定参数类型,这个进程的值,和任务最终的值。

2.这个doInBackground()方法自动执行在工作线程中。

3.onPreExecute(), onPostExecute(), and onProgressUpdate()所有的方法是在UI线程中调用

4.通过doInBackground()返回值传递到onPostExecute()方法中

5.你可以任何时候在doInBackground()方法里调用publishProgress()方法从而在你的UI线程中去执行onProgressUpdate()方法

6.你可以在任何时候取消这个任务,在任何线程里。

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.

谨慎的:有一个问题你可能会遇到,当使用一个工作线程由于运行配置改变(例如当用户屏幕的方向发生改变)在你Activity会意外重启.这可能销毁你的工作线程。想知道在那些重启的Activity中保持怎样去保持你的任务和怎么样适当的去取消任务,当Activity销毁的时候。查看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.

远程被调用的方法首先必须支持线程安全--例如在一个绑定的服务。当实现一个在IBinder里调用方法源于IBinder运行时发生在同一线程时。这个方法在在调用者的线程里被执行。然而,当你调用的方法发生在其他线程时,这个方法是和IBinder在同一个进程,系统维护的线程池上执行的线程。(它不能在这个进程的UI线程中执行)。例如,一个service的onBind()方法会被service进程的UI线程调用,方法实现在onBind()返回的对象上(例如,一个实现RPC方法的子类),这个方法会被线程池中的线程调用。因为一个service可以有多个客户端。多个线程池中的线程可以在同一时间执行相同的IBinder方法。因此必须实现进程安全。

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.

同样的,一个content provider会接收源于其它线程的数据请求,尽管ContentResolver类和ContentProvider类隐藏了进程通信时怎么管理的,ContentProvider响应那些请求---这些query(), insert(), delete(), update(), and getType()方法--被Content providerd的进程中的一个线程池里的线程调用,而不是进程中的UI线程。因为这些方法在任何时候被任何数量的线程调用,他们必须实现线程安全。

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 reassembling 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.

Android为使用远程进程调用(RPCs)进程通信提供一种机制(IPC),这种机制中的一个方法被一个activity或者是其它应用组件调用,但是远程的(在另一个进程)执行返回结果给调用者。这个需要分解一个方法调用和它的数据到一个操作系统能理解的水平,它本地进程和空间地址传播到远程进程和空间地址。然后在那里重新组装和重新调用,然后在相反的方向传播返回值。Android提供所有代码去执行这些IPC事务,所以你会集中定义和实现RPC 程序接口。

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

去执行IPC,你的应用必须绑定一个服务,使用bindService()。更多的信息,看Seivices开发指导。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: