Android 进程 和 线程 Process and Threads

Processes and Threads 进程与线程 Processes and Threads 进程与线程简述俗话说的好“纸上得来终觉浅 绝知此事要宫刑”,多线程编程可以最大限度地利用多核心和操作系统的系统,是提高程序运行性能常用的方法!而进程(Process)和进程(Thread)也是计算机利于最基本的概念,虽然如此,当我们真正的想开发高效率的并发应用,却发现对于他们的理解还是不够深刻!在Android中,当app启动时,系统会为这个applica 阅读详情

官方文档 : 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开发指南。

2025年情感分析(SA)综述——论文阅读报告 阅读详情

相关推荐

UE5实战技巧:TextRender高效集成中文字体与材质优化

本文针对UE5中TextRender组件显示中文的常见问题,提供了一套完整的实战解决方案。详细讲解了如何通过手动创建字体资产、精准控制字符集来优化性能,并重点介绍了通过调整材质中的Lerp节点参数(如设为-85, 92)来解决中文字体显示残缺和边缘模糊等核心难题,帮助开发者实现高效且美观的中文文本渲染。

weixin_28040125的博客 379

Android - 线程 Thread

一个线程总是由另一个线程启动,所以总有一条特殊的线程即主线程。

HugMua的博客 1111

新版股票配资系统源码/股票分析系统技术方案

新版股票配资系统;全套源码支持新股申购功能,包含C#+MySQL开发的后台系统及Spring框架,采用C/S架构。注意:本源码仅限技术学习、功能测试及模拟交易使用,严禁用于非法用途,违者责任自负。

q318136906的博客 1642

进程(process)和线程(thread)介绍

本文主要介绍进程(process)和线程(thread)的相关知识。一开始,CPU只有在执行完一份完整的任务代码后,才能执行下一份。后来,通过把CPU时间分片,可以让多个任务“看似”同时地执行。为了更好地区分这些“同时”执行的任务以及整合各自对应的资源,人们就提出了process这个概念。如下:每个process都有独立的下列资源:process之间的通信要通过IPC(inter-process communication)来实现。原始的process只有一个“thread of control”来执行任务

liitdar的博客 1万+

Arduino应用——PWM控制直流电机风扇

Arduino应用——PWM控制直流电机风扇PWM原理实验器件功能描述如何改变文本的样式插入链接与图片实现代码生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 最近在使用arduino UNO开发板完成课程小作业。其中一个要求设计一个电风扇控制系统,要求能够通过PWM调节风扇的转速。期间搜索了许多例程和方法,但受限于器件,效果不

hypecycle的博客 2万+

【Get深一度】小波分析概念1——紧支撑集是什么意思,通俗解释

最近学到小波,在仿真中也用到了紧支撑函数;紧支撑性越好,说明能量越集中;用最通俗的话来讲,紧支撑是这样的: 对于函数f(x),如果自变量x在 0附近的取值范围内,f(x)能取到 C; 而在此之外,f(x)取值为 0; 那么这个函数f(x)就是紧支

Trey_优快云 的优快云博客 8348

进程(process) vs 线程(Thread)

🚀 多方面理解进程(process)线程(Thread)本文主要介绍了进程和线程的基本概念、区别以及操作系统如何调度线程的方式。同时,还介绍了线程锁的核心原理和实现方式。在多线程编程中,理解进程和线程的概念以及线程锁的使用,对于保证程序的安全性和性能非常重要。参考 : https://zhuanlan.zhihu.com/p/258049386。

Bruce__taotao的博客 2489

电子病历编辑器源码(Springboot+原生HTML)

应用场景包括:电子病历书写、体温单录入、全平台信息采集、检验检查报告、不良事件上报等。 此外,电子病历编辑器软件还适用于医生工作站的病历编辑、护士工作站的护理记录输入、PASC/LIS/RIS报告编辑打印、病案首页、出院小结、病程记录、手术记录、各种知情书、康复及精神学科用的量表、临床路径用表单界面等等。 这些应用场景都涉及到了医疗文书编辑的需求,因此电子病历编辑器软件在这些场景中具有广泛的应用价值。

xingchen优快云的博客 3894

android 线程分析工具,Android代码分析工具-Threads

有时候我们需要关注应用本身创建了多少个线程,应用back后还有哪些线程在后台运行。这时我们需要用到Threads这个工具。来看一个简单的例子我们在onCreate方法里创建了一个Thread(111)public class TestActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceSta...

weixin_39599705的博客 363

win10 离线安装.Net Framework3.5

起因,安装软件比如3dmax2014等需要.Net Framework3.5支撑,那么需要安装低版本的.Net Framework3.5 闲话少说。 1.下载 NetFx3.cab 链接: https://pan.baidu.com/s/124to7F3BOy4yAlY61OjbDg 提取码: kixu 2.将NetFx3.cab 放入 系统盘的windows目录下(示例 C:\Wi...

m0_37615458的博客 7715

自考计算机系统原理(第六章计算机系统概论)-13015

名词解释 I/O 硬件 I/O软件 用户空间I/O软件 内核空间I/O 软件 系统调用处理程序 系统调用服务例程 设备驱动程序 中断服务程序 系统级1/O函数 虚拟文件系统 文件描述符 文件元数据 流缓冲区 索引节点 目录文件 目录项 系统打开文件表 磁盘高速缓存 高速缓存 RAM I / O 控制方式 程序直接控制I/O 就绪状态 中断控制I/O 中断屏蔽字 多重中断 中断嵌套 DMA 方式 DMA 控制器 设备控制器 I/O端口 控制端口 数据端口 状态端口 I/O 地址空间 独立编址方式 统一编址方

qq_23872947的博客 1150

android8.1环境下 android Threads线程实现

Android native的Thread类是Android提供的一个基础类,源码路径: system\core\libutils\include\utils\Thread.h system\core\libutils\Threads.cpp 该类提供的基础功能涵盖了线程的生命周期:创建、运行、销毁。主要成员函数如下: 0、本身继承于RefBase,所以具有相应的一些特性 // Invoked after creation of initial strong pointer/reference. ..

we1less的博客 840

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Android开发者指南-进程和线程-Processes and Threads[原创译文]

进程和线程 (参考了http://leybreeze.com/?p=532,修正一些重大错误,增加新版本的内容。) 版本:Android 3.2   快速查看 ·           默认情况下,每个应用程序运行在各自的进程中,应用程序中的所有组件也都运行在其中。 ·           activity中所有运行缓慢的、阻塞的操作都应该

houyu_1983的专栏 1018

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

android sdk Process and Threads 翻译

当一个应用程序刚开始运行,同时这个应用程没有其他的正在运行的组件,android系统将会以一个单独运行的线程方式为这个应用程序开启一个新的linux进程。默认的,一个应用程序上的所有的组件运行在相同的进程和线程(被叫做“main”的线程上)上。如果一个应用程序组件开始运行时,同时为这个应用程序也存在一个进程(因为这个应用程序存在的其他的组件),那么这个组件在这个进程中运行并且使用正在执行...

amwxytu75574的博客 158

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Processes and Threads 进程和线程,android移动开发基础案例代码

(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 component

m0_64604466的博客 405

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 execut

linghu_java的专栏 1740

android的进程和线程(Processes and Threads)

当一个应用程序组件启动,应用程序没有任何其他组件上运行,Android系统的启动与执行一个新的Linux进程。默认情况下,同一个应用程序的所有组件在同一个进程和线程(称为“主”线程)上运行。如果一个应用程序组件启动和已经存在用于该应用程序的处理(因为从应用程序的另一个组件存在),则该组件被启动的过程中,并使用执行相同的线程。你可以在你的应用中安排另外的进程去运行,亦可以为任何进程创建创造额外线程。

1007

threads, processes, process groups and sessions

主要是相关知识的初步整理。 session > process group > process > thread ps j可以查看进程的PID,PPID,PGID,SID信息

烂笔头 660

进程和线程(Processes and Threads)——翻译自developer.android.com

线程和进程Processes and Threads 当你的app的组件启动了,并且app中没有其他的组件的时候,Android系统会自动为为这个应用启动一个linux进程,其中有一个执行的线程。默认时,一个app的所有的组件运行在同一个进程的同一个线程,也就是主线程。如果一个组件启动的时候,app已经有一个进程了,(因为可能这个应用中其他的组件已经运行了),那么这个组件就在这个进程中被

WALLEZhe的博客 2966

Process and Thread 进程和线程

http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html 当一个应用程序组件开启,而该应用程序没有其他组件在运行,那么Android系统会为这个应用程序启动一个新的Linux进程,一个单独线程来执行这些操作。一般来说,一个应用程序中的所有组件应该是跑在同一个进程和线程(主线程,called

pipisky2006的专栏 1674

Android Process and Thread 进程和线程

http://developer.android.com/guide/topics/fundamentals/processes-and-threads.html 当一个应用程序组件开启,而该应用程序没有其他组件在运行,那么Android系统会为这个应用程序启动一个新的Linux进程,一个单独线程来执行这些操作。一般来说,一个应用程序中的所有组件应该是跑在同一个进程和线程(主线程,calle

longlyboyhe的专栏 660

进程与线程监控:mobileperf如何帮助优化Android应用多任务处理

在Android应用开发中,进程与线程的合理管理直接影响应用的响应速度和稳定性。mobileperf作为一款专业的Android性能测试工具,提供了强大的进程与线程监控功能,帮助开发者实时追踪应用的多任务处理情况,精准定位性能瓶颈。本文将详细介绍如何使用mobileperf监控Android应用的进程与线程,以及如何利用监控数据优化应用性能。 ## 为什么需要监控进程与线程? Android应

gitblog_00487的博客 757

Android------Process and Threads

当一个应用程序组件启动时(这个应用程序还没有其它的组件在运行),那么android系统会为这个应用程序启动一个linux进程(这个进程有一个单一的线程) 默认情况下,一个应用程序的所有组件运行在同一个进程中,而且是运行在主线程中。如果一个应用程序的进程已经存在,此时再启动这个应

shuhuai007的专栏 967

Process and Threads

Process and Threads 当一个Application启动时,如果该application此时没有其他Component在运行,Android System此时会为该application启动一个新的进程。 默认情况下,一个application中所有组件都运行在同一个进程和线程(主线程)中。 如果一个application启动时,该application已经有一个进程(已经有组件启...

weixin_30266885的博客 137

【2】Android Processes And Threads

Android 中的进程和线程基本知识点: 什么是进程?什么是线程?二者的关系 四大组件的 android:process 属性 进程的五级重要层次结构 进程的分类:前台进程、可见进程、服务进程、后台进程、空进程 Android 单线程模式的两条基本规则 在工作线程访问UI的几种办法: 使用 AsyncTask 线程安全方法 参考文档: (1)、官方GUIDE

happy_horse的博客 473

Processes and Threads

Briefly introduce to processes and threads.

userqiaohaibin的专栏 410
上一篇: Android Actionar overflow 不显示的问题
下一篇: Android Service
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

皮克桃在写代码

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

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

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

打赏作者

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

抵扣说明:

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

余额充值