Android 进程 和 线程 Process and Threads

本文深入探讨Android中进程与线程的概念,介绍组件如何在进程中运行,以及主线程的作用和重要性。同时,讲解了如何避免阻塞主线程,确保应用流畅运行,并介绍了AsyncTask的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官方文档 : Process 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.

译:当一个应用程组件序第一次启动也就是说这个程序没有其他组件(Components)正在运行(已经启动),则Android 系统会创建一个新的包含单个执行线程的Linux 进程,默认情况下,同一个应用程序的所有组件(Components)都运行在同一个进程和线程(Main Thread or Ui Thread)里面.如果应用程序某个组件启动的时候已经存在应程序的进程了(因为这个应用的其他组件已经启动运行了),那么这个组件会在已存在的进程和线程中启动运行,不过你可以设置你应用程序不同的组件运行在不同的进程里面,并且也可以为任意进程创建额外的线程。

进程 Process

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.

译:默认情况下,一个应用程序的所有组件(Components)都运行在同一个进程中,大多数应用程序都不应该去改变它。然而,如果你发现你需要去控制某一个组件所属进程你可以在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>,<provider> 元素都支持 android:process 属性 ,它可以指定组件运行的进程,你可以通过设置该属性来指定每一个组件运行在它指定的进程中,或者设置让某几个进程共享一个进程而其他几个组件不共享。你也可以通过该属性让不同应用的组件运行在用一个进程中(前提是这几个应用共享同一个 Linux user ID 并且用的同一个签名文件签名)

注:可以通过设置不同应用的manifest element 的 android:sharedUserId为同一个值来让不同应用share 同一个 Linux user ID

The <application> element also supports an android:process attribute, to set a default value that applies to all components.

译:manifest 文件中的<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 在某些时刻会结束掉一个进程,当设备运行内存不足,可又有其他为用户提供更紧急服的进程需要更多内存。(比如用户启动启动一个新的应用,启动这个应用的进程对于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.

译:Andorid 通过衡量进程对于用户的相对重要性来决定什么时候结束掉什么样的进程。例如,相对于一个拥有可见activity的进程,android更乐意杀死那些activity不可见的进程。因此,决定是否杀死一个进程是通过运行在该进程中的组件的状态来决定的。终止进程判断规则在下面讨论

进程生命周期Process Lifecyle

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.

译:Andorid 系统会尽可能长时间的保持应用程序进程,但为了新的或者更重要的进行,android系统也不得不结束 old 进程来回收内存。为了决定保留或终止哪个进程,系统根据进程内运行组件及这些组件的状态,把每个进程都划入一个“重要性层次结构”中。重要性低的进程首先会被清除,然后是下一个最低的,依此类推,这都是回收系统资源所必要做的。

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个等级,下面按照进程的重要性依次列出了这5种类型,第一种的进程重要性是最高的,也将是最后被杀死的。

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

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.

1.前台进程
一个用户当前操作所必须的线程。如果一个进程满足以下任一条件则被认为前台进程

  • 进程包含正在与用户交互的Activity(即Activity 处于running 状态 OnResum 已经被调用)
  • 进程中包含一个Service ,并且该Service正绑定到一个正在于用户交互的Activity
  • 进程中包含一个Service ,并且该Service处于运行运行状态,并且调用了startForeground() 方法
  • 进程中包含一个正在执行生命周期方法 onCreate,OnStart or OnDestroy 的Service
  • 进程中包含一个正在执行onReceive方法的BroadcastReceiver

通常情况下,在任何时刻前台进程都是比较少的,当内存处于比较低的状态不能保持他们同时运行的时候,结束掉他们会被当作最后手段。通常,设备这时候已经到了内存分页状态(memory paging state)的地步,因此结束掉一些前台进程是为让用户交互界面能得到即使的响应。

注:这也是为什么有时候我们在使用一些配置低的android手机会突然遇到设备自动重启(和关机自动重启不一样,关机重启是所有都会重启,这个只是重启某些东西)的原因,以前本人亲自在一个手机上打开一个图片很多的网页,在滑动网页加载更多的图片的时候,就会遇到手机黑屏重启,因为这时候内存太低了,连很多系统服务和launcher都不能维持运行了。

2.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). This might occur, for example, if the foreground activity started a dialog, which allows the previous activity to be seen behind it.
  • It hosts a Service that’s bound to a visible (or foreground) activity.

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

2.可视进程
一个没有前台组件,但是任然影响用户在屏幕上所见内容的进程。满足一下任一条件被视为可见进程。

  • 如果进程包含一个Activity,虽然该Activity 没有在前台,但是任然被用户所能看见(onPause 方法被调用),例如,一个foreground Activity 启动了一个Dialog,并且该Dialog 允许之前启动它的Activity 在Dialog后面能被看见。
  • 进程包含一个绑定到可视或者处于前台的Activity

可视进程也被视为非常重要的,除非在无法保证所有前台进程都能同时维持的情况下才会杀死可视进程

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

译: 3.服务进程
一个进程包含一个以startService()方式启动的Service,并且Service 不会上升到上诉两级别,虽然服务进程不直关系着用户看得见的东西,但是他们通常做着用户关心的事情(例如在后台播放音乐,已经下载某东西)。因此系统会尽量保证他们运行,除非没有足够的内存来保持所有的前台进程和可视进程运行,系统才会结束掉服务进程。

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

译:4.后台进程
一个进程包含的所有Activity都处于不可见的状态(activity 的onStop() 方法被调用),这些线程对用户体验没有直接影响,系统可以为了前台进,可视,或者服务进程程在任意时刻杀死后台进程回收内存,通常会有很多后台进程在运行,他们被保存在一个叫LRU(最近最少使用)的list 里面,用来确保最后被用户使用的Activity所在的进程最后被杀死,如果一个Activity正在的实现了其生命周期方法,并且保存了其当前的状态,那么杀死此类进程不会对用户体验产生可见的影响,因为当用户回到这个Activity的时候,这Activity会恢复所有它可见的状态(原来保存的状态),关于保存或恢复更多的信息可以查看 Activitys 的文档

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

译:空进程
一个进程不持有任何“活的” 应用组件(比如activity ,service都onDestroy了)。保持这类进程的唯一目的是用作缓存,以便在下一次组件启动的能够加快时间。为了在进程缓存和内核缓存间平衡系统整体资源,系统经常会终止这种进程。

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 基于当前进程中活动组件的重要性会把进程等级评估为最高的哪一个级别,例如,一个进程持有一个Service 和一个 可视的activity,那么android 会把该进程

视为可视进程而不是服务进程。

注:这句话是什么意思呢?就是说一个进程中可能有很多组件,比如Activity,Service 等,有的activity 处于 running和用户交互 ,有的处于 onPause,还有的Activity 处于onStop,那么Android会把该进程评估为这几个等级中最高的哪一个等级,即running对应的 前台进程 。

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中的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进程的,所以,如果activity需要启动一个长时间运行的操作,则为其启动一个服务service会比简单地创建一个工作线程更好些——尤其是在此操作时间比activity本身存在时间还要长久的情况下。比如,一个activity要把图片上传至Web网站,就应该创建一个服务来执行之,即使用户离开了此activity,上传还是会在后台继续运行。不论activity发生什么情况,使用服务可以保证操作至少拥有“服务进程”的优先级。同理,上一篇中的广播接收器broadcast receiver也是使用服务而非线程来处理耗时任务的。

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

译:当一个应用被启动的时候,系统会为该应用创建一个执行线程,被称为“主”线程,主线程非常重要,应为它负者把事件分发到恰当的用户界面wigets,包含绘画事件。它也是应用程序于android UI 组件(android.widget and android.view packages包下)进行交互的线程,因此 主线程有时候也被称为 UI 线程。

注:一个进程只有一个也就是唯一 一个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 线程中实例化。对每个组件的系统调用也都是由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 线程把这个事件派发给这个按钮,这个按钮会把自己的状态置为,同时再发送一个显示区域已失效(invalidate)的请求到事件队列中。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 线程被阻塞的时候,所有事件都不能分发包括绘画线程。从用户的角度看,应用程序出现了挂起,更糟糕的是如果UI线程阻塞超过一定时间(目前是5秒),系统将会弹出一个ANR (程序没有响应)的dialog给用户,这时候用户可能会退出你的应用,如果他不高兴很有可能直接卸载你的应用。

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:

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

译:此外 android UI 组件包不是线程安全的。因此你不能再非UI线程里面操作UI—你必须在UI线程里面进行所有的UI相关的操作。因此Android 单线程模式需要遵守两个简单的规则:
1.不要阻塞UI 线程
2.不要在UI 线程以外的地方访问android UI 组件

工作线程Wroker treads

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:

译: 例如,下面展示了一段代码,在响应点击事件的时候新启动了一个线程去下载网络上的图片。并显示在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 组件—这个例子在工作线程中修改了ImageView。这可能导致不明确、不可预见的后果,要跟踪这种情况也是很困难很耗时间的

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:

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

译:为了解决上面代码的问题,Android 提供了集中方法在其他线程访问UI线程。下面列出了可以解决这问题的几个方法:

  • Activity.runOnUiThread(Runnable)
  • View.post(Runnable)
  • View.postDelayed(Runnable, long)

比如说,可以使用View.post(Runnable)方法来修正上面的代码:

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.

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.

译:现在以上代码实现的方式是线程安全的:网络操作在单独的线程中,对ImageView 的操作在UI 线程中。
但是随着操作变得越来越复杂,这种方式的代码也会变得很复杂和难以维护。为了让工作线程处理更多复杂的交互,你可以在工作线程中用一个Handler来处理UI 线程发送过来的消息。也许最好的方式就是继承AsyncTask 类,此类简化了一些工作线程和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.

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.

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

译:AysncTask 允许你在用户界面执行异步工作,它在工作线程中执行阻塞操作(耗时操作,会阻塞UI 的操作),等执行完成后再把执行结果发送给UI 线程,次过程中不需要你去处理线程或者handler 自身。

要使用AysncTask 你必须实例化它的一个子类,并且实现doInBackground()方法,该方法运行在后台线程池里面,如果你需要更新你的UI ,那么你应该实现onPostExecute()方法,该方法会递交doInBackground() 方法执行的结并运行在UI 线程中,因此你可以在该方法中安全的更新你的UI。做完这些后,你可以在UI线程中调用它的execute()方法来运行这个task。(AysncTask 只能在UI 线程中调用,因为在AysncTask 中有一个Handler,为了实现操作UI线程的功能,所以必须在UI线程实现Handler 。具体可以看AysncTask 的源码,)
例如,你可以用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.

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:

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.

译:现在UI是安全的,代码也得到简化,因为任务分解成了工作线程内完成的部分和UI线程内完成的部分。

你应该通过阅读 AsyncTask 的reference 来对如何使用这个类有一个完全的理解,这儿只是一个快速的概括其实如何工作的:

  • 可以用generics(泛型)来指定参数、进度值和任务最终值的类型。
  • doInBackground()方法在工作线程中会自动执行。onPreExecute(), onPostExecute(), and onProgressUpdate() 在UI 线程被调用
  • doInBackground()的返回值会传给onPostExecute()
  • 在doInBackground()内的任何时刻,都可以调用publishProgress()来执行UI线程中的onProgressUpdate()。(比如更新进程条)
  • 可以在任何时刻、任何线程内取消任务。

注意:在使用工作线程时,可能遇到的另一个问题是由于运行配置的改变(比如用户改变了屏幕方向)导致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.

译: 对于一个能被远程调用的方法,比如绑定服务(bond service)中的方法,这是理所当然的(应该要写成线程安全的)。当一个实现在IBinder 中的方法被调用,如果调用者和IBinder 运行在同一个进程中,那么这个方法会运行在调用者的线程中,如果调用者是在另外一个进程中,那么这个方法会运行在一个由系统维护和IBinder同一个进程里面的线程池中的某一个线程里面(不是运行在这IBinder 所在进程的UI线程里面),比如,即使一个服务的onBind()方法是被service’s 进程的UI线程调用,但是调用onBind()返回实现了IBinder接口的对象中的方法将也只会运行在线程池里面。因为一个Service 可以有多个客户端,在同一个时候就可能有多个线程调用同一个实现了IBinder 接口的对象中的方法。因此IBinder 对象的方法必须实现成安全的。

注:这段文字对应很多初学者来说不是很好理解,具体是什么呢?意思就是说我们在实现Service相关功能的时候,如果要用到IBinder (在Service onBind方法中返回的对象)对象来进行客服端和服务端通信,那么IBinder 对象中的方法就应该被写成线程安全的,不然如果客户所在的进程和Service 运行所在的进程不是同一个进程的时候,客服端调用IBinder对象的方法将不会运行在UI线程(Service 的UI 线程)中,而是运行在一个由系统维护的线程池中,那么这种情况下如果Service 有多个客服端,就有可能造成多个线程同时访问IBinder 的某一个方法。
再此还要特别强调一点 不管Service 和客户端是否运行在同一个进程中,如果IBinder 对象的方法中有执行耗时操作都不要在客服端的UI线程中调用该方法。因为不管IBinder 对象的方法运行在系统维护的线程池中还是和调用者线程中(调用者可能是在UI线程调用也可能是在非UI线程调用)都会让调用线程阻塞直到方法执行完毕。

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 可以接受来自其他进程的请求数据,ContentProvider 中的 query(),insert(),delete(),update()和getType() 等方法会被ContentPovider 所在进程的线程池里面的线程调用(非UI 线程),尽管ContentResolver 和ContentProvider 隐藏了进程间通信的具体细节。因为这些方法可能在同一个时刻被多个线程同时调用,所有这些方法也必须实现线程安全。

进程间通信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.

译:Android利用远程过程调用(remote procedure call,RPC)提供了一种进程间通信(IPC)机制,通过这种机制,被activity或其他应用程序组件调用的方法将(在其他进程中)被远程执行,而所有的结果将被返回给调用者。这就要求把方法调用及其数据分解到操作系统可以理解的程度,并将其从本地的进程和地址空间传输至远程的进程和地址空间,然后在远程进程中重新组装并执行这个调用。执行后的返回值将被反向传输回来。Android提供了执行IPC事务所需的全部代码,因此只要把注意力放在定义和实现RPC编程接口上即可。

要执行IPC,应用程序必须用bindService()绑定到服务上。详情请参阅服务Services开发指南。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮克桃在写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值