第一章:第三節:Concurrency in 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的結構及其用法和應用程序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章