欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

android 进程与线程 - 开发文档翻译 - 线程

程序员文章站 2022-05-06 08:18:57
...

由于本人英文能力实在有限,不足之初敬请谅解,希望大家落脚同时能指出不足。

本博客只要没有注明“转”,那么均为原创,转贴请注明本博客链接链接

 

android 进程与线程 - 开发文档翻译 - 进程

android 进程与线程 - 开发文档翻译 - 线程

 

其他系列的翻译

android activity开发文档翻译 - 1 - 基础篇

android activity开发文档翻译 - 2 - 生命周期篇

 

android task与back stack 开发文档翻译 - 1

android task与back stack 开发文档翻译 - 2

android task与back stack 开发文档翻译 - 3

 

android Fragment开发文档翻译 - 1

android Fragment开发文档翻译 - 2

 

本系列并没有对原文100%翻译,也没有100%的贴出原文

 

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.

当一个应用被启动,系统建立一个为这个应用建立一个线程来执行它,称作主线程。

这个线程非常重要,因为它负责分配事件到恰当的UI部件中,包括绘画事件。

它也是你的应用中与Android 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线程用实例证明,并且系统从那个线程调用每一个组件

因此,相应系统回调的方法(如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线程分发触摸事件到小部件中,按顺序设置自己的触摸状态并且发送一个无效的请求到事件队列中。

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线程被阻塞超过几秒钟(现在大概5秒)用户就会看到臭名昭著的"application not responding"(应用程序无想用)(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:

另外,Andoid UI工具包不是线程安全的。

所以你必须使用一个工作线程控制你的UI - 你必须在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工具包

 

 

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线程对你应用程序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线程外部访问Android UI工具包 - 这个例子从工作线程修改了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:

为了修正这个问题,Android提供几种从其他线程访问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:

例如你可以通过使用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.

现在的这个实现是线程安全的:网络操作在一个单独的线程中完成而在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线程的消息分发。

也许最好的解决方案,是继承AsyncTask,它可以简单的执行工作线程需要与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上执行异步工作。

它在工作线程中执行阻塞操作并且发布结果到UI线程,并不需要你自己来处理线程也不需要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并且实现运行在后台线程池中的doInBackground()回调函数。

为了更新你的UI,你应该实现onPostExecute(),它从doInBackground()传达结果并且运行在UI线程中,所以你可以安全的更新你的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线程是安全的并且代码很简单,因为它把应该在UI线程的工作独立到一个工作线程出来。

 

如何使用AsyncTask的部分略,参见AsyncTask 文档

 

 

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被销毁时你如何恰当的取消任务,参见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.

对于可以被远程调用的方法这是基本的事实 - 例如在绑定的service中的方法。

当一个在IBinder实现的方法调用发生在与IBinder运行的同一进程中的时候,这个方法在调用者的线程中被执行。

然而,当这个调用发生在其他进程中时,这个方法在与IBinder相同的进程中,系统维护的线程池中的线程上被执行(它不运行在这个进程的UI线程上)

例如,一个service的onBind()方法会被service进程的UI线程调用,方法实现在onBind()返回的对象上(例如,一个实现RPC方法的子类),此方法会被池中线程调用

因为一个service可以有多个客户端,多个线程池中的线程可以在相同时间使用同一个IBinder方法。

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(),和getType()方法 - 被content provider的进程中的一个线程池的线程调用,而不是进程中的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 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.

Android为使用远程过程调用(RPCs)进程间通信提供一种机制,在这种机制中一个方法被一个activity或者其他应用组件调用,但是远程的(在另一个进程)执行并且结果返回给调用者(不是被调用者)。

这使得能够分解一个方法调用和它的数据到一个操作系统能理解的层面,把它们从一个本地进程和空间地址转化到一个远程的进程和空间地址,然后在那里重新合成并重新执行这个调用

然后返回值反向传送。

Android提供所有的代码来执行这些IPC事务,所以你能集中精力定义和实现RPC程序接口。

 

 

 

To perform IPC, your application must bind to a service, using bindService(). 

要执行IPC,你的应用必须使用bindService()绑定到一个service上。

For more information, see the Services developer guide.

更多信息参见Services开发向导。

 

原文地址如下,英文水平实在有限,希望拍砖同时能给予指正。

http://developer.android.com/guide/components/processes-and-threads.html

 

 

 

转贴请保留以下链接

本人blog地址

http://su1216.iteye.com/

http://blog.csdn.net/su1216/