Android並發編程

來源:互聯網
上載者:User

標籤:

Android的並發編程,即多線程開發,而Android的多線程開發模型也是源於Java中的多執行緒模式。
所以本篇也會先講一些Java中的多線程理念,再講解具體涉及的類,最後深入Android中的並發情境和實踐。

並發什麼是並發

舉個很簡單的栗子,當你一邊在擼擼擼,一邊在看小視頻,同時在做兩件事,這就是並發。

咳,年輕人節制啊。

並發的好處提高資源使用率

當一個任務並沒有完全佔用系統資源,就可以利用並發來提高資源使用率,同時也能更快地完成任務。

當你的右手在幹些什麼的時候,左手是不是在沒事做呢?那就也用起來唄。
(某次聚會,一名騎馬的漢子說自己左右互搏(lu)特厲害)。

在程式任務上更加精簡

就拿上一個栗子來說,左手做什麼,右手做什麼,任務明確分配好,又能同時進行,既提高了效率,邏輯又清晰。

更好的響應程式

這個拿Android用戶端舉個栗子,上傳圖片時,當前介面還是正常運轉沒有卡死,圖片也正常上傳,既保證了介面被響應,又保證圖片可以上傳。

並發的風險並發的代價
  • 需要佔用更多的資源。
  • 設計好一個並發程式並不容易。
  • 並發的資源互動問題複雜。
並發的隱患
  • 濫用資源導致系統不穩定
  • 結果與預期不符
  • 出現BUG難以排查
線程篇進程是什麼

就拿Android中的App來說,一般來說一個app就是一個進程,(除了特殊的手段開啟了多個進程,這裡不深入這個話題,就是一個一對多的關係)。

線程是什麼

進程只是一個程式、任務的統稱,但是卻不能執行任務,真正執行任務的是線程,所以線程是由進程建立的,一個進程可以建立多個線程。

線程可以調度資源等等,在這裡只需要瞭解大致的概念就好,如果要深入可以學習一下作業系統。

進程與線程的關係

人腦就相當於是CPU,想做一件事的時候,這個任務就是一個進程了,需要運用手腳等器官去完成這個任務,而手腳器官就可以理解成一個個線程,去做了不同的事,從而完成任務。

單線程

還是用Android舉栗子,當你在手機上操作的時候,這個被稱之為UI線程(之後會詳解)。而一個最基本的app,不需要複雜的功能時,就只有一個UI線程和我們互動,那麼這個app就是個單線程的。一般的程式面向使用者的線程就是UI線程,也稱之為主線程,單線程程式,其實就是只有一個主線程的程式。

多線程

多個進程可以算是並發,但是我們所說的並發情境,大部分是在一個進程中的,而並發就是由線程完成的,多個線程同時執行任務,就稱之為並發。

以下為多線程工作:

多線程並發過程中會遇到的問題1. 資源共用

A線程要寫檔案C,B線程也要寫檔案C,這個時候就好像你拿著兩隻筆同時往紙上寫東西,寫出來的是什麼自己也不知道。

這個時候我們需要一個類似於鎖的東西,當C被A在寫的時候,B不能寫,B要等A寫完了才能繼續寫。

至於這個鎖到底是什麼會在後面繼續講到。

3. 死結問題

死結的四個條件是:

  • 禁止搶佔:no preemption

  • 持有和等待:hold and wait

  • 互斥:mutual exclusion

  • 迴圈等待:circular waiting

預防死結就是至少破壞這四個條件其中一項,即破壞“禁止搶佔”、破壞“持有等待”、破壞“資源互斥”和破壞“迴圈等待”。

舉個例子:

A在B那邊割包皮,B把A割壞了,A佔著B的床位,要B賠錢,B要A讓出床位才給錢。雙方僵持不下。

線程如何去用

在Java中,線程通常就是指Thread這個類,或者實現了Runnable的類,其實Thread這個類也是實現了Runnable介面的,可以看一下Runnable介面的代碼:

裡面就是一個run方法需要被實現。

再看一下Thread類的聲明:

確實是一個實現了Runnable的類。

那麼Thread類中擁有start()方法,和run()方法,下面用run()方法直接調用
得到資訊:

發現其實和外面的線程是在同一個線程上。

而調用start()方法得到的資訊是:

發現線程名不一樣了,用start會開啟一個新的線程,而run還是在當前線程執行。

另外在Java1.5之後,還有Callable、Future和FutureTask,在這裡就不詳細介紹,還有線程的wait、
yield、sleep等在下一章會一起詳細介紹。

線程的優先順序

在Java中,線程的優先順序有1~10,而預設的是5。1最低,10最高。在Thread類中有三個常量:

  • MIN_PRIORITY = 1

  • NORM_PRIORITY = 5

  • MAX_PRIORITY = 10

在同一個線程池中的線程優先順序是相同的。

JVM會根據線程的優先順序去搶先調度,然而線程的優先順序只能保證搶佔資源的機率較大,並不能保障線程的執行順序,所以不能過於依賴設定線程的優先順序。

線程池

頻繁地建立和銷毀線程會導致效能大幅度降低,這肯定不是你希望的。

線程池的出現,就是為瞭解決這個問題,根據java中提供不同的線程池機制,有效地提高資源使用率。

直接在代碼中建立Thread、Runnable去start或者run容易出現不可預測的問題,在java1.5開始,引入了java.util.concurrent包,其中有個並發的架構:Executor,使用ExecutorService替代直接操作線程類,而Executors是用來建立線程池的,內部提供了很多靜態方法去建立你想要的線程池,不需要你再手動去建立實現。
看一下關於Executor中的類和介面的大致的成員與關係:

關於這些類如何使用,以及有什麼特性,下一章會作介紹。

隊列

在java中提到隊列肯定會想起Queue,而線程隊列用的是BlockingQueue,這是個介面,在concurrent包中有好幾個類實現了這個介面。

介紹一下BlockingQueue常用的方法

  會異常 返回是否成功 會阻塞 設定等待時間
入隊列 add(e) offer(e) put(e) offer(e, timeout, unit)
出隊列 remove() poll() take() poll(time, unit)
查看值 element() peek() none none
安全執行緒鎖

在前面講過死結,死結是由於使用不當引起的一種現象,而這裡的鎖是人工幹預的,讓並發按照你的意思走。

在java中的鎖有synchonrized、Lock。鎖的出現主要是為瞭解決安全執行緒問題。

關於線程的狀態會在下一章講鎖的機制時候再講,因為線程的狀態會影響到鎖。

安全執行緒的集合

因為多線程訪問資源可能會造成資料不一致或者資料汙染,而某些集合會用一些鎖或者同步機製做了處理。

安全執行緒的集合有:HashTable、SynchronizedCollection、ConcurrentHashMap、Vector等。

線程安不安全的首要前提是在多線程訪問同一個對象的情況下。

Android並發編程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.