Concurrency in Android

    • Correctness issues in concurrent programs(并发程序中的正确性问题)
    • Liveness issues in concurrent programs(并行程序中的活跃性问题)
    • Android-specific concurrency issues(Android特定的并发问题)
      • The Activity lifecycle
      • Manipulating the user interface(操纵用户界面)
    • Android-specific concurrency constructs(Android特定的并发构造)

The low-level constructs of concurrency in Android are those provided by the Java language: java.lang.Thread, java.lang.Runnable, and the synchronized and volatile keywords.
Android中的低级并发结构是Java语言提供的:java.lang.Thread,java.lang.Runnable以及synchronized和volatile关键字。

Higher-level mechanisms introduced to Java 5 in the java.util.concurrent package, such as Executors, atomic wrapper classes, locking constructs, and concurrent collections, are also available for use in Android applications.
java.util.concurrent包中引入Java 5的高级机制(如Executors,原子包装类,锁定构造和并发集合)也可用于Android应用程序。

We can start new threads of execution in our Android applications just as we would in any other Java application, and the operating system will schedule some CPU time for those threads.
我们可以在Android应用程序中启动新的执行线程,就像在任何其他Java应用程序中一样,操作系统将为这些线程安排CPU时间。

To do some work off the main thread, we can simply create a new instance of java. lang.Thread, override its run() method with the code we want it to execute, and invoke its start() method.
要在主线程上做一些工作,我们可以简单地创建一个新的 java.lang.Thread实例,通过覆盖其run()方法来执行我们的代码,并调用其start()方法。

While starting new threads is easy, concurrency is actually a very difficult thing to do well. Concurrent software faces many issues that fall into the two broad categories: correctness (producing consistent and correct results) and liveness (making progress towards completion).
虽然启动新线程很容易,但并发实际上是一件非常困难的事情。 并发软件面临许多问题,这些问题分为两大类:正确性(产生一致和正确的结果)和活跃性(向完成方向取得进展)。

Correctness issues in concurrent programs(并发程序中的正确性问题)

A common example of a correctness problem occurs when two threads need to modify the value of the same variable based on its current value. Let’s imagine that we have an integer variable myInt with the current value of 2.
当两个线程需要根据其当前值修改同一变量的值时,会出现正确性问题的常见示例。 让我们假设我们有一个整数变量 myInt,当前值为2。

In order to increment myInt, we first need to read its current value and then add 1 to it. In a single threaded world, the two increments would happen in a strict sequence—we read the initial value 2, add 1 to it, set the new value back to the variable, then repeat the sequence. After the two increments, myInt holds the value 4.
为了增加myInt,我们首先需要读取它的当前值然后再加1。 在单线程中,两个增量将以严格的顺序发生 - 我们读取初始值2,向其添加1,将新值设置回变量,然后重复序列。 在两个增量之后,myInt保持值4。

In a multithreaded environment, we run into potential timing issues. It is possible that two threads trying to increment the variable would both read the same initial value (2), add 1 to it, and set the result (in both cases, 3) back to the variable.
在多线程环境中,我们遇到了潜在的时序问题。 尝试增加变量的两个线程可能都会读取相同的初始值(2),向它添加1,并将结果(两个线程都为中值都为3)都设置回变量。

Both threads have behaved correctly in their localized view of the world, but in terms of the overall program, we clearly have a correctness problem; 2 + 2 should not equal 3! This kind of timing issue is known as a race condition.
两个线程在其自身的代码中都表现正确,但就整体计划而言,我们显然存在正确性问题; 2 + 2不应该等于3! 这种计时问题被称为竞争条件。

A common solution to correctness problems such as race conditions is mutual exclusion—preventing multiple threads from accessing certain resources at the same time. Typically, this is achieved by ensuring that threads acquire an exclusive lock before reading or updating shared data.
正确性问题(例如竞争条件)的常见解决方案是互斥 - 防止多个线程同时访问某些资源。 通常,这是通过确保线程在读取或更新共享数据之前获得独占锁来实现的。

Liveness issues in concurrent programs(并行程序中的活跃性问题)

Liveness can be thought of as the ability of the application to do useful work and make progress towards goals. Liveness problems tend to be an unfortunate side effect of the solution to correctness problems. By locking access to data or system resources, it is possible to create bottlenecks where many threads are contending for access to a single lock, leading to potentially significant delays.
活性可以被认为是应用程序完成有用工作并朝着目标前进的能力。活跃性问题往往是解决正确性问题的一个不幸的副作用。通过锁定对数据或系统资源的访问,可能产生瓶颈,其中许多线程都在争用对单个锁的访问,从而导致潜在的严重延迟。

Worse, where multiple locks are used, it is possible to create a situation where no thread can make progress because each requires exclusive access to a lock that another thread currently owns—a situation known as a deadlock.
更糟糕的是,在使用多个锁的情况下,可能会创建一个没有线程可以进行的情况,因为每个线程都需要对另一个线程当前拥有的锁的独占访问 - 这种情况称为死锁。

Android-specific concurrency issues(Android特定的并发问题)

There are two additional problems facing developers of concurrent Android applications which are specific to Android.
并发Android应用程序的开发人员面临两个特定于Android的额外问题。

The Activity lifecycle

Android applications are typically composed of one or more subclasses of android. app.Activity. An Activity instance has a very well-defined lifecycle that the system manages through the execution of lifecycle method callbacks, all of which are executed on the main thread.
Android应用程序通常由b android.app.Activity 的一个或多个子类组成。 Activity实例有一个非常明确定义的生命周期,系统通过执行生命周期方法回调来管理,所有这些都在主线程上执行。

An Activity instance that has been completed should be eligible for garbage collection, but background threads that refer to the Activity or part of its view hierarchy can prevent garbage collection and create a memory leak.
已经完成的活动实例应该可以进行垃圾收集,但是引用该活动或其视图层次结构的一部分的后台线程可以防止垃圾收集并创建内存泄漏。

Similarly, it is easy to waste CPU cycles (and battery life) by continuing to do background work when the result can never be displayed because Activity has finished.
同样,由于Activity已经完成,因此在结果永远无法显示时继续执行后台工作很容易浪费CPU周期(和电池寿命)。

Finally, the Android platform is free at any time to kill processes that are not the user’s current focus. This means that if we have long-running operations to complete, we need some way of letting the system know not to kill our process yet!
最后,Android平台在任何时候都可以自由地终止那些不是用户当前关注的进程。这意味着,如果我们要完成长时间运行的操作,我们需要某种方式让系统知道不要终止我们的进程!

All of this complicates the do-not-block–the-main-thread rule because we need to worry about canceling background work in a timely fashion or decoupling it from the Activity lifecycle where appropriate.
所有这些都使请勿阻塞主线程规则复杂化,因为我们需要担心及时取消后台工作,或者在适当的情况下将其与活动生命周期分离。

Manipulating the user interface(操纵用户界面)

The other Android-specific problem lies not in what you can do from the UI thread, but in what you cannot do:
另一个Android特有的问题不在于你可以从UI线程做什么,而在于你不能做什么:

You cannot manipulate the user interface from any thread other than the main thread.
不能从主线程以外的任何线程操作用户界面。

This is because the user-interface toolkit is not thread-safe, that is, accessing it from multiple threads may cause correctness problems. In fact, the user-interface toolkit protects itself from potential problems by actively denying access to user-interface components from threads other than the one that originally created those components.
这是因为用户界面工具包不是线程安全的,也就是说,从多个线程访问它可能会导致正确性问题。 实际上,用户界面工具包通过主动拒绝从最初创建这些组件的线程以外的线程访问用户界面组件来保护自己免受潜在问题的影响。

The final challenge then lies in safely synchronizing background threads with the main thread so that the main thread can update the user interface with the results of the background work.
最后的挑战在于安全地将后台线程与主线程同步,以便主线程可以使用后台工作的结果更新用户界面。

Android-specific concurrency constructs(Android特定的并发构造)

The good news is that the Android platform provides specific constructs to address the general issues of concurrency, and to solve the specific problems presented by Android.
好消息是,Android平台提供了特定的构造来解决并发性的一般问题,并解决了Android所提出的特定问题。

There are constructs that allow us to defer tasks to run later on the main thread, to communicate easily between cooperating threads, and to issue work to managed pools of worker threads and re-integrate the results.
有一些构造允许我们推迟任务在主线程上运行,方便在协作线程之间进行通信,并向工作线程的托管池发出工作,并重新集成结果。

There are solutions to the constraints of the Activity lifecycle both for medium-term operations that closely involve the user-interface and for longer-term work that must be completed even if the user leaves the application.
对于与用户界面密切相关的中期操作以及即使用户离开应用程序也必须完成的长期工作,Activity活动周期的约束都有解决方案。

While some of these constructs were only introduced with newer releases of the Android platform, all are available through the support libraries and, with a few exceptions, the examples in this book target devices that run API level 7 (Android 2.1) and above.
虽然其中一些结构仅在Android平台的较新版本中引入,但所有这些都可以通过支持库获得,除了少数例外,本书中的示例针对运行API级别7(Android 2.1)及更高版本的设备。

The rest of this book discusses these Android-specific constructs and their usage and applications
本书的其余部分将讨论这些特定于Android的结构及其用法和应用程序。

更多相关文章

  1. android的进程与线程
  2. Android 网络多线程断点下载
  3. Android之 UI主线程

随机推荐

  1. asp.net core实例教程之异常处理与静态文
  2. 总结关于winfrom注意点
  3. 总结.Net MVC实现长轮询实例
  4. asp.net core实例教程之如何设置中间件
  5. 关于接口类型的10篇课程推荐
  6. 用微信PC端dll库实现截图的实例代码
  7. asp.net core实例教程之项目结构
  8. 有关ListView的文章推荐10篇
  9. .Net MVC+Data Table实现分页+排序的实例
  10. asp.net core实例教程之配置