切換語言為:簡體
Android常見面試題總結

Android常見面試題總結

  • 爱糖宝
  • 2024-08-13
  • 2062
  • 0
  • 0

這段時間麵了幾家公司,也跟不同的面試官切磋了一些面試題,有的沒啥難度,有的則是問到了我的知識盲區,沒辦法,Android能問的東西太多了,要全覆蓋到太難了,既然沒法全覆蓋,那麼只好亡羊補牢,將這些沒答上來的題目做下記錄,讓自己如果下次遇到了可以答上來

TCP與UDP有哪些差異

這道題回答的不全,僅僅只是將兩個協議的概念說了一下,但是真正的差異卻沒有真正答上來,後來查詢了一下資料,兩者的差異如下

  • TCP是傳輸控制協議,是面向連接的協議,傳送資料前需要建立連線,TCP傳輸的資料不會丟失,不會重複,會按照順序到達

  • 與TCP相對的,UDP是無連線的協議,傳送資料前不需要建立連線,資料沒有可靠性

  • TCP的通訊類似於打電話,需要確認身份後纔可以通話,而UDP更像是廣播,不關心對方是不是接收,只需要播報出去即可

  • TCP支援點對點通訊,而UDP支援一對一,一對多,多對一,多對多

  • TCP傳輸的是位元組流,而UDP傳輸的是報文

  • TCP首部開銷為20個位元組,而UDP首部開銷是8個位元組

  • UDP主機不需要維持複雜的連線狀態表

TCP的三次握手

這道題以及下面那道雖然說上來了,但是也沒有說的很對,僅僅只是說了下每次握手或者揮手的目的,中間的過程沒有說出來,以下是三次握手以及四次揮手的詳細過程

  • 第一次握手:客戶端將SYN置為1,隨機生成一個初始序列號seq傳送給服務端,客戶端進入SYN_SENT狀態

  • 第二次握手:服務端收到客戶端的SYN=1之後,知道客戶端請求建立連線,將自己的SYN置1,ACK置1,產生一個ack=seq+1,並隨機產生一個自己的初始序列號,傳送給客戶端,服務端進入SYN_RCVD狀態

  • 第三次握手:客戶端檢查ack是否為序列號+1,ACK是否為1,檢查正確之後將自己的ACK置為1,產生一個ack=伺服器的seq+1,傳送給伺服器;進入ESTABLISHED狀態;伺服器檢查ACK為1和ack為序列號+1之後,也進入ESTABLISHED狀態;完成三次握手,連線建立

TCP的四次揮手

  • 第一次揮手:客戶端將FIN設定為1,傳送一個序列號seq給服務端,客戶端進入FIN_WAIT_1狀態

  • 第二次揮手:服務端收到FIN之後,傳送一個ACK為1,ack為收到的序列號加一,服務端進入CLOSE_WAIT狀態,這個時候客戶端已經不會再向服務端傳送資料了

  • 第三次揮手:服務端將FIN置1,傳送一個序列號給客戶端,服務端進入LAST_ACK狀態

  • 第四次揮手:客戶端收到伺服器的FIN後,進入TIME_WAIT狀態,接著將ACK置1,傳送一個ack=序列號+1給伺服器,伺服器收到後,確認ack後,變為CLOSED狀態,不再向客戶端傳送資料。客戶端等待2* MSL(報文段最長壽命)時間後,也進入CLOSED狀態。完成四次揮手

從瀏覽器輸入地址到最終顯示頁面的整個過程

這個真的知識盲區了,誰會平時沒事在用瀏覽器的時候去思考這個問題呢,結果一查居然還是某大廠的面試題,算了也瞭解下吧

  1. 第一步,瀏覽器查詢DNS,獲取域名對應的ip地址

  2. 第二步,獲取ip地址後,瀏覽器向伺服器建立連線請求,發起三次握手請求

  3. 第三步,連線建立好之後,瀏覽器向伺服器發起http請求

  4. 第四步,伺服器收到請求之後,根據路徑的引數對映到特定的請求處理器進行處理,並將處理結果以及相應的檢視返回給瀏覽器

  5. 第五步,瀏覽器解析並渲染檢視,若遇到js,css以及圖片等靜態資源,則重複向伺服器請求相應資源

  6. 第六步,瀏覽器根據請求到的資料,資源渲染頁面,最終將完整的頁面呈現在瀏覽器上

為什麼Zygote程序使用socket通訊而不是binder

應用層選手遇到偏底層問題就頭疼了,但是這個問題還是要知道的,畢竟跟我們app的啟動流程相關

  1. 原因一:從初始化時機上,Binder通訊需要在Android執行時以及Binder驅動已經初始化之後才能使用,而在這之前,Zygote已經啟動了,所以只能使用socket通訊

  2. 原因二:從出現的先後順序上,Zygote相比於Binder機制,更早的被設計以及投入使用,所以在Android的早期版本中,Android就已經使用socket來監聽其他程序的請求

  3. 原因三:從使用上,socket通訊不依賴於Binder機制,它是一種簡單通用的IPC機制,也不需要複雜的介面定義

  4. 原因四:從相容性上來講,socket是一種跨平臺的IPC機制,可以在不同的作業系統和環境中使用。

  5. 原因五:從效能上來講,由於使用Zygote通訊並不是頻繁的操作,所以使用socket通訊不會對系統性能造成顯著影響

  6. 原因六:從安全性上來講,使用socket可以確保只有系統中特定的服務如system_server才能與Zygote通訊,從而提升一定的安全性

使用Binder的好處有哪些

上面那個問題問好了緊接著就是這道題,我嗯嗯啊啊的零碎說了幾個,肯定也是不過關的,回頭查了下資料,使用Binder的優勢如下

  • 從效率上來講,Binder比較高效,相比較於其他幾種程序的通訊方式(管道,訊息佇列,Socket,共享記憶體),Binder只需要複製一次記憶體就好了,而除了共享記憶體,其餘都都要複製兩次記憶體,共享記憶體雖然不需要複製,但是實現方式複雜,所以綜合考慮Binder佔優勢

  • 使用的是更加便於理解,更簡單的物件導向的IPC通訊方式

  • Binder既支援同步呼叫,也支援非同步呼叫

  • Binder使用UID和PID來驗證請求的來源,這樣可以確保每個Binder事務可以精確到發起者,為程序間的通訊提供了保障

  • Binder是基於c/s架構,架構清晰明確,Server端與Client端相對獨立

  • Binder有一套易於使用的API供程序間通訊,將複雜的內部實現隱藏起來

如果一個執行緒連續呼叫兩次start,會怎樣?

會怎樣?誰知道呀,正常人誰會沒事去呼叫兩次start呢?但是這個還真有人問了,我只能說沒遇到過,後來回去自己試了下才知道

Android常見面試題總結

如上述程式碼所示,有一個執行緒,然後連續呼叫了兩次start方法,當我們執行一下這段程式碼後,得到的結果如下

Android常見面試題總結

可以發現執行緒有正常執行,但同時也因為多調了一次start而丟擲了異常,這個異常在start方法裡面就能看到

Android常見面試題總結

有一個狀態為started,正常第一次啟動執行緒時候,started為false,所以是不會丟擲異常的,started為true的地方是在下面這個位置

Android常見面試題總結

呼叫了native方法nativeCreated後,started狀態位才變成true,這個時候如果再去呼叫start方法,那麼必然會丟擲異常

如何處理協程併發的資料安全

之前遇到過這麼個問題,併發處理的協程之間是否可以保證資料安全,這個由於之前有實驗過,所以想都沒想就說可以保證資料安全,但面試官只是呵呵了一下,我捉摸著難道不對嗎,後來回去試了一下才發現,不一定就能保證資料安全,看下面這段程式碼

Android常見面試題總結

這段程式碼裡面在runBlocking中建立了1000個協程,每一個協程都對變數count做自增操作,最後把結果列印出來,我們預期的是列印出的結果就是1000,實際結果如下

Android常見面試題總結

看到的確就是1000,沒啥毛病,多試幾次也是一樣的,但是如果換一種寫法試試看呢

Android常見面試題總結

原本都是runBlocking裡面的子協程,現在將這些協程變成非runBlocking的子協程,結果是不是還是1000呢,看下結果

Android常見面試題總結

明顯不是了,所以併發處理的協程,並不能保證資料安全,那麼如何可以讓資料安全呢,有以下幾個辦法

原子類

Android常見面試題總結

這個好理解,同處理執行緒安全差不多

channel

Android常見面試題總結

receive函式只有等到阻塞佇列裡面有資料的時候纔會執行,沒有資料的時候會一直等待,所以這就能保證這些協程可以併發執行,不過要注意的是這裏的Channel一定要設定佇列大小,不然程式會一直阻塞,receive一直在等待佇列裡面有資料

mutex

Android常見面試題總結

使用互斥鎖的方式,withLock函式內部執行了獲取鎖跟釋放鎖邏輯,將變數count保護起來,實現資料安全,除此之外,還可以使用lockunLock函式來實現,程式碼如下

Android常見面試題總結

總結

總的來講自己在系統層面,偏底層的那些問題上,還是掌握的不多,這個也跟自己多年徘徊在應用層開發有關,底層知識用到的不多,自然也就忽略了,但是如果面試的話,就算是麵的應用層,也是需要知道一些底層方面的知識,不然面試官隨便問幾個,你不會,別人會,崗位不就被別人拿走了嗎

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.