1. 程式人生 > 其它 >位元組跳動內部學習資料洩露!Android專案開發如何設計整體架構?看看這篇文章吧!

位元組跳動內部學習資料洩露!Android專案開發如何設計整體架構?看看這篇文章吧!

前言

想要成為一名優秀的Android開發,你需要一份完備的知識體系,在這裡,讓我們一起成長為自己所想的那樣~。

此篇文章是初中高階工程師學習文章,知識體系較為完整。有如下特點:
[1]知識結構全面
[2]跟隨當下技術潮流實時更新
[3]可用於面試 & 學習
[4]知識分為文字部分和視訊部分,任性選擇
[5]正確的職業規劃
[6]方便工作過程中遺忘知識點快速查詢

1.執行緒池的好處? 四種執行緒池的使用場景,執行緒池的幾個引數的理解?

參考回答:

使用執行緒池的好處是減少在建立和銷燬執行緒上所花的時間以及系統資源的開銷,解決資源不足的問題。如果不使用執行緒池,有可能造成系統建立大量同類執行緒而導致消耗完記憶體或則“過度切換”的問題,歸納總結就是

  • 重用存在的執行緒,減少物件建立、消亡的開銷,效能佳。
  • 可有效控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
  • 提供定時執行、定期執行、單執行緒、併發數控制等功能。

Android中的執行緒池都是直接或間接通過配置ThreadPoolExecutor來實現不同特性的執行緒池.Android中最常見的類具有不同特性的執行緒池分別為:

  • newCachedThreadPool:只有非核心執行緒,最大執行緒數非常大,所有執行緒都活動時會為新任務建立新執行緒,否則會利用空閒執行緒 ( 60s空閒時間,過了就會被回收,所以執行緒池中有0個執行緒的可能 )來處理任務.
    • 優點:任何任務都會被立即執行(任務佇列SynchronousQuue相當於一個空集合);比較適合執行大量的耗時較少的任務.
  • newFixedThreadPool:只有核心執行緒,並且數量固定的,所有執行緒都活動時,因為佇列沒有限制大小,新任務會等待執行,當執行緒池空閒時不會釋放工作執行緒,還會佔用一定的系統資源。
    • 優點:更快的響應外界請求
  • newScheduledThreadPool:核心執行緒數固定,非核心執行緒(閒著沒活幹會被立即回收數)沒有限制.
    • 優點:執行定時任務以及有固定週期的重複任務
  • newSingleThreadExecutor:只有一個核心執行緒,確保所有的任務都在同一執行緒中按序完成
    • 優點:不需要處理執行緒同步的問題

通過原始碼可以瞭解到上面的四種執行緒池實際上還是利用 ThreadPoolExecutor 類實現的

2.Android中還了解哪些方便執行緒切換的類?

參考回答:

  • AsyncTask:底層封裝了執行緒池和Handler,便於執行後臺任務以及在子執行緒中進行UI操作。
  • HandlerThread:一種具有訊息迴圈的執行緒,其內部可使用Handler。
  • IntentService:是一種非同步、會自動停止的服務,內部採用HandlerThread。

3.講講AsyncTask的原理

參考回答:

  • AsyncTask中有兩個執行緒池(SerialExecutor和THREAD_POOL_EXECUTOR)和一個Handler(InternalHandler),其中執行緒池SerialExecutor用於任務的排隊,而執行緒池THREAD_POOL_EXECUTOR用於真正地執行任務,InternalHandler用於將執行環境從執行緒池切換到主執行緒。
  • sHandler是一個靜態的Handler物件,為了能夠將執行環境切換到主執行緒,這就要求sHandler這個物件必須在主執行緒建立。由於靜態成員會在載入類的時候進行初始化,因此這就變相要求AsyncTask的類必須在主執行緒中載入,否則同一個程序中的AsyncTask都將無法正常工作。

4.IntentService有什麼用 ?

參考回答:

IntentService可用於執行後臺耗時的任務,當任務執行完成後會自動停止,同時由於IntentService是服務的原因,不同於普通Service,IntentService可自動建立子執行緒來執行任務,這導致它的優先順序比單純的執行緒要高,不容易被系統殺死,所以IntentService比較適合執行一些高優先順序的後臺任務。

5.直接在Activity中建立一個thread跟在service中建立一個thread之間的區別?

參考回答:

  • 在Activity中被建立:該Thread的就是為這個Activity服務的,完成這個特定的Activity交代的任務,主動通知該Activity一些訊息和事件,Activity銷燬後,該Thread也沒有存活的意義了。
  • 在Service中被建立:這是保證最長生命週期的Thread的唯一方式,只要整個Service不退出,Thread就可以一直在後臺執行,一般在Service的onCreate()中建立,在onDestroy()中銷燬。所以,在Service中建立的Thread,適合長期執行一些獨立於APP的後臺任務,比較常見的就是:在Service中保持與伺服器端的長連線。

6.ThreadPoolExecutor的工作策略 ?

參考回答:ThreadPoolExecutor執行任務時會遵循如下規則

  • 如果執行緒池中的執行緒數量未達到核心執行緒的數量,那麼會直接啟動一個核心執行緒來執行任務
  • 如果執行緒池中的執行緒數量已經達到或則超過核心執行緒的數量,那麼任務會被插入任務佇列中排隊等待執行。
  • 如果在第2點無法將任務插入到任務佇列中,這往往是由於任務佇列已滿,這個時候如果線上程數量未達到執行緒池規定的最大值,那麼會立刻啟動一個非核心執行緒來執行任務。
  • 如果第3點中執行緒數量已經達到執行緒池規定的最大值,那麼就拒絕執行此任務,ThreadPoolExecutor會呼叫RejectedExecutionHandler的rejectedExecution方法來通知呼叫者

7.Handler、Thread和HandlerThread的差別?

參考回答:

  • Handler:在android中負責傳送和處理訊息,通過它可以實現其他支線執行緒與主執行緒之間的訊息通訊。
  • Thread:Java程序中執行運算的最小單位,亦即執行處理機排程的基本單位。某一程序中一路單獨執行的程式。
  • HandlerThread:一個繼承自Thread的類HandlerThread,Android中沒有對Java中的Thread進行任何封裝,而是提供了一個繼承自Thread的類HandlerThread類,這個類對Java的Thread做了很多便利的封裝。HandlerThread繼承於Thread,所以它本質就是個Thread。與普通Thread的差別就在於,它在內部直接實現了Looper的實現,這是Handler訊息機制必不可少的。有了自己的looper,可以讓我們在自己的執行緒中分發和處理訊息。如果不用HandlerThread的話,需要手動去呼叫Looper.prepare()和Looper.loop()這些方法。

8.ThreadLocal的原理

參考回答:

ThreadLocal是一個關於建立執行緒區域性變數的類。使用場景如下所示:

  • 實現單個執行緒單例以及單個執行緒上下文資訊儲存,比如交易id等。
  • 實現執行緒安全,非執行緒安全的物件使用ThreadLocal之後就會變得執行緒安全,因為每個執行緒都會有一個對應的例項。 承載一些執行緒相關的資料,避免在方法中來回傳遞引數。

當需要使用多執行緒時,有個變數恰巧不需要共享,此時就不必使用synchronized這麼麻煩的關鍵字來鎖住,每個執行緒都相當於在堆記憶體中開闢一個空間,執行緒中帶有對共享變數的緩衝區,通過緩衝區將堆記憶體中的共享變數進行讀取和操作,ThreadLocal相當於執行緒內的記憶體,一個區域性變數。每次可以對執行緒自身的資料讀取和操作,並不需要通過緩衝區與 主記憶體中的變數進行互動。並不會像synchronized那樣修改主記憶體的資料,再將主記憶體的資料複製到執行緒內的工作記憶體。ThreadLocal可以讓執行緒獨佔資源,儲存於執行緒內部,避免執行緒堵塞造成CPU吞吐下降。

在每個Thread中包含一個ThreadLocalMap,ThreadLocalMap的key是ThreadLocal的物件,value是獨享資料。

9.多執行緒是否一定會高效(優缺點)

參考回答:
多執行緒的優點:

  • 方便高效的記憶體共享 - 多程序下記憶體共享比較不便,且會抵消掉多程序程式設計的好處
  • 較輕的上下文切換開銷 - 不用切換地址空間,不用更改CR3暫存器,不用清空TLB
  • 執行緒上的任務執行完後自動銷燬

多執行緒的缺點:

  • 開啟執行緒需要佔用一定的記憶體空間(預設情況下,每一個執行緒都佔512KB)
  • 如果開啟大量的執行緒,會佔用大量的記憶體空間,降低程式的效能
  • 執行緒越多,cpu在呼叫執行緒上的開銷就越大
  • 程式設計更加複雜,比如執行緒間的通訊、多執行緒的資料共享

綜上得出,多執行緒不一定能提高效率,在記憶體空間緊張的情況下反而是一種負擔,因此在日常開發中,應儘量

  • 不要頻繁建立,銷燬執行緒,使用執行緒池
  • 減少執行緒間同步和通訊(最為關鍵)
  • 避免需要頻繁共享寫的資料
  • 合理安排共享資料結構,避免偽共享(false sharing)
  • 使用非阻塞資料結構/演算法
  • 避免可能產生可伸縮性問題的系統呼叫(比如mmap)
  • 避免產生大量缺頁異常,儘量使用Huge Page
  • 可以的話使用使用者態輕量級執行緒代替核心執行緒

10.多執行緒中,讓你做一個單例,你會怎麼做
參考回答:

  • 多執行緒中建立單例模式考慮的因素有很多,比如執行緒安全 -延遲載入-程式碼安全:如防止序列化攻擊,防止反射攻擊(防止反射進行私有方法呼叫) -效能因素
  • 實現方法有多種,餓漢,懶漢(執行緒安全,執行緒非安全),雙重檢查(DCL),內部類,以及列舉

11.除了notify還有什麼方式可以喚醒執行緒

參考回答:

  • 當一個擁有Object鎖的執行緒呼叫 wait()方法時,就會使當前執行緒加入object.wait 等待佇列中,並且釋放當前佔用的Object鎖,這樣其他執行緒就有機會獲取這個Object鎖,獲得Object鎖的執行緒呼叫notify()方法,就能在Object.wait 等待佇列中隨機喚醒一個執行緒(該喚醒是隨機的與加入的順序無關,優先順序高的被喚醒概率會高)
  • 如果呼叫notifyAll()方法就喚醒全部的執行緒。注意:呼叫notify()方法後並不會立即釋放object鎖,會等待該執行緒執行完畢後釋放Object鎖。

12.什麼是ANR ? 什麼情況會出現ANR ?如何避免 ? 在不看程式碼的情況下如何快速定位出現ANR問題所在 ?

參考回答:

  • ANR(Application Not Responding,應用無響應):當操作在一段時間內系統無法處理時,會在系統層面會彈出ANR對話方塊
  • 產生ANR可能是因為5s內無響應使用者輸入事件、10s內未結束BroadcastReceiver、20s內未結束Service
  • 想要避免ANR就不要在主執行緒做耗時操作,而是通過開子執行緒,方法比如繼承Thread或實現Runnable介面、使用AsyncTask、IntentService、HandlerThread等

更多學習和討論,歡迎加入我們的知識星球!

點選這裡加入我們吧!

群內有許多來自一線的技術大牛,也有在小廠或外包公司奮鬥的碼農,我們致力打造一個平等,高質量的Android交流圈子,不一定能短期就讓每個人的技術突飛猛進,但從長遠來說,眼光,格局,長遠發展的方向才是最重要的。

這裡有2000+小夥伴,讓你的學習不寂寞~·