日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android bitmap转图片_这是一份面向Android开发者的复习指南

發布時間:2023/12/8 Android 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android bitmap转图片_这是一份面向Android开发者的复习指南 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

來自:簡書,作者:九心

鏈接:https://www.jianshu.com/p/b3c1b9c6dd40

前言

相信很多同學都會有這樣的感受,前三天剛剛復習的知識點,今天問的時候怎么就講不出個所以然了呢?

本文的目的就是致力于幫助大家盡可能的建立Android知識體系,希望大家會喜歡~

必讀

知識結構

覆蓋的知識點有Android、Java、Kotlin、Jvm、網絡和設計模式。

面向人群

正在求職的中高級Android開發

食用指南

和大部分人一樣,我在復習完第一遍Android知識的情況下,看到相關的知識回答的仍然不能夠令自己滿意。

在第二遍系統復習的時候,我著重記住每個知識點的關鍵字,根據這些關鍵字拼湊出大概的知識點,最后看到每個知識點的時候,就知道大概會問哪些內容,達到這種境界以后,你就可以從容的面對每次面試了。

簡單的做法就是為每個知識點建立腦圖,盡可能把自己想到的關鍵點羅列出來,也就是下面每個章節前面的腦圖。

除此以外,我還為大家提供了可能會問到的面試題。

一、Android基

1. Activity

# Activity的四大啟動模式,以及應用場景?

Activity的四大啟動模式:

  • standard:標準模式,每次都會在活動棧中生成一個新的Activity實例。通常我們使用的活動都是標準模式。

  • singleTop:棧頂復用,如果Activity實例已經存在棧頂,那么就不會在活動棧中創建新的實例。比較常見的場景就是給通知跳轉的Activity設置,因為你肯定不想前臺Activity已經是該Activity的情況下,點擊通知,又給你再創建一個同樣的Activity。

  • singleTask:棧內復用,如果Activity實例在當前棧中已經存在,就會將當前Activity實例上面的其他Activity實例都移除棧。常見于跳轉到主界面。

  • singleInstance:單實例模式,創建一個新的任務棧,這個活動實例獨自處在這個活動棧中。

2. 屏幕適配

# 平時如何有使用屏幕適配嗎?原理是什么呢?

平時的屏幕適配一般采用的頭條的屏幕適配方案。簡單來說,以屏幕的一邊作為適配,通常是寬。

原理:設備像素px和設備獨立像素dp之間的關系

px = dp * density

假設UI給的設計圖屏幕寬度基于360dp,那么設備寬的像素點已知,即px,dp也已知,360dp,所以density = px / dp,之后根據這個修改系統中跟density相關的知識點即可。

3. Android消息機制

# Android消息機制介紹?

Android消息機制中的四大概念:

  • ThreadLocal:當前線程存儲的數據僅能從當前線程取出。

  • MessageQueue:具有時間優先級的消息隊列。

  • Looper:輪詢消息隊列,看是否有新的消息到來。

  • Handler:具體處理邏輯的地方。

過程:

  • 準備工作:創建Handler,如果是在子線程中創建,還需要調用Looper#prepare(),在Handler的構造函數中,會綁定其中的Looper和MessageQueue。

  • 發送消息:創建消息,使用Handler發送。

  • 進入MessageQueue:因為Handler中綁定著消息隊列,所以Message很自然的被放進消息隊列。

  • Looper輪詢消息隊列:Looper是一個死循環,一直觀察有沒有新的消息到來,之后從Message取出綁定的Handler,最后調用Handler中的處理邏輯,這一切都發生在Looper循環的線程,這也是Handler能夠在指定線程處理任務的原因。

  • # Looper在主線程中死循環為什么沒有導致界面的卡死?

  • 導致卡死的是在Ui線程中執行耗時操作導致界面出現掉幀,甚至ANR,Looper.loop()這個操作本身不會導致這個情況。

  • 有人可能會說,我在點擊事件中設置死循環會導致界面卡死,同樣都是死循環,不都一樣的嗎?Looper會在沒有消息的時候阻塞當前線程,釋放CPU資源,等到有消息到來的時候,再喚醒主線程。

  • App進程中是需要死循環的,如果循環結束的話,App進程就結束了。

  • 建議閱讀:

    《Android中為什么主線程不會因為Looper.loop()里的死循環卡死?》

    https://www.zhihu.com/question/34652589

    # IdleHandler介紹?

    介紹:

    IdleHandler是在Hanlder空閑時處理空閑任務的一種機制。

    執行場景:

    • MessageQueue沒有消息,隊列為空的時候。

    • MessageQueue屬于延遲消息,當前沒有消息執行的時候。

    會不會發生死循環:

    答案是否定的,MessageQueue使用計數的方法保證一次調用MessageQueue#next方法只會使用一次的IdleHandler集合。

    4. View事件分發機制和View繪制原理

    剛哥的《Android開發藝術探索》已經很全面了,建議閱讀。

    5. Bitmap

    # Bitmap的內存計算方式?

    在已知圖片的長和寬的像素的情況下,影響內存大小的因素會有資源文件位置和像素點大小。

    像素點大小:

    常見的像素點有:

    • ARGB_8888:4個字節

    • ARGB_4444、ARGB_565:2個字節

    資源文件位置:

    不同dpi對應存放的文件夾

    比如一個一張圖片的像素為180*180px,dpi(設備獨立像素密度)為320,如果它僅僅存放在drawable-hdpi,則有:

    橫向像素點?=?180?*?320/240?+?0.5f?=?240?px
    縱向像素點?=?180?*?320/240?+?0.5f?=?240?px

    如果它僅僅存放在drawable-xxhdpi,則有:

    180?*?

    所以,對于一張180*180px的圖片,設備dpi為320,資源圖片僅僅存在drawable-hdpi,像素點大小為ARGB_4444,最后生成的文件內存大小為:

    橫向像素點?=?180?*?320/240?+?0.5f?=?240?px
    縱向像素點?=?180?*?320/240?+?0.5f?=?240?px
    內存大小?=?240?*?240?*?2?=?115200byte?約等于?112.5kb

    建議閱讀:

    《Android Bitmap的內存大小是如何計算的?》

    https://ivonhoe.github.io/2017/03/22/Bitmap&Memory/

    # Bitmap的高效加載?

    Bitmap的高效加載在Glide中也用到了,思路:

  • 獲取需要的長和寬,一般獲取控件的長和寬。

  • 設置BitmapFactory.Options中的inJustDecodeBounds為true,可以幫助我們在不加載進內存的方式獲得Bitmap的長和寬。

  • 對需要的長和寬和Bitmap的長和寬進行對比,從而獲得壓縮比例,放入BitmapFactory.Options中的inSampleSize屬性。

  • 設置BitmapFactory.Options中的inJustDecodeBounds為false,將圖片加載進內存,進而設置到控件中。

  • 二、Android進階

    Android進階中重點考察Android Framework、性能優化和第三方框架。

    1. Binder

    # Binder的介紹?與其他IPC方式的優缺點?

    Binder是Android中特有的IPC方式,引用《Android開發藝術探索》中的話(略有改動):

    從IPC角度來說,Binder是Android中的一種跨進程通信方式;Binder還可以理解為虛擬的物理設備,它的設備驅動是/dev/binder;從Android Framework來講,Binder是Service Manager連接各種Manager和對應的ManagerService的橋梁。從面向對象和CS模型來講,Client通過Binder和遠程的Server進行通訊。

    基于Binder,Android還實現了其他的IPC方式,比如AIDL、Messenger和ContentProvider。

    與其他IPC比較:

    • 效率高:除了內存共享外,其他IPC都需要進行兩次數據拷貝,而因為Binder使用內存映射的關系,僅需要一次數據拷貝。

    • 安全性好:接收方可以從數據包中獲取發送發的進程Id和用戶Id,方便驗證發送方的身份,其他IPC想要實驗只能夠主動存入,但是這有可能在發送的過程中被修改。

    # Binder的通信過程?Binder的原理?

    圖片:

    其實這個過程也可以從AIDL生成的代碼中看出。

    原理:

    Binder的結構:

    • Client:服務的請求方。

    • Server:服務的提供方。

    • Service Manager:為Server提供Binder的注冊服務,為Client提供Binder的查詢服務,Server、Client和Service Manager的通訊都是通過Binder。

    • Binder驅動:負責Binder通信機制的建立,提供一系列底層支持。

    從上圖中,Binder通信的過程是這樣的:

  • Server在Service Manager中注冊:Server進程在創建的時候,也會創建對應的Binder實體,如果要提供服務給Client,就必須為Binder實體注冊一個名字。

  • Client通過Service Manager獲取服務:Client知道服務中Binder實體的名字后,通過名字從Service Manager獲取Binder實體的引用。

  • Client使用服務與Server進行通信:Client通過調用Binder實體與Server進行通信。

  • 更詳細一點?

    Binder通信的實質是利用內存映射,將用戶進程的內存地址和內核的內存地址映射為同一塊物理地址,也就是說他們使用的同一塊物理空間,每次創建Binder的時候大概分配128的空間。數據進行傳輸的時候,從這個內存空間分配一點,用完了再釋放即可。

    2. 序列化

    # Android有哪些序列化方式?

    為了解決Android中內存序列化速度過慢的問題,Android使用了Parcelable。

    對比SerializableParcelable
    易用性簡單不是很簡單
    效率
    場景IO、網絡和數據庫內存中

    3. Framework

    Zygote孕育進程過程?

    # Activity的啟動過程?

    建議閱讀:

    《3分鐘看懂Activity啟動流程》

    https://www.jianshu.com/p/9ecea420eb52

    # App的啟動過程?

    介紹一下App進程和System Server進程如何聯系:

    App進程

    • ActivityThread:依賴于Ui線程,實際處理與AMS中交互的工作。

    • ActivityManagerService:負責Activity、Service等的生命周期工作。

    • ApplicationThread:System Server進程中ApplicatonThreadProxy的服務端,幫助System Server進程跟App進程交流。

    • System Server:Android核心的進程,掌管著Android系統中各種重要的服務。

    具體過程:

    • 用戶點擊App圖標,Lanuacher進程通過Binder聯系到System Server進程發起startActivity。

    • System Server通過Socket聯系到Zygote,fork出一個新的App進程。

    • 創建出一個新的App進程以后,Zygote啟動App進程的ActivityThread#main()方法。

    • 在ActivtiyThread中,調用AMS進行ApplicationThread的綁定。

    • AMS發送創建Application的消息給ApplicationThread,進而轉交給ActivityThread中的H,它是一個Handler,接著進行Application的創建工作。

    • AMS以同樣的方式創建Activity,接著就是大家熟悉的創建Activity的工作了。

    # Apk的安裝過程?

    建議閱讀:

    《Android Apk安裝過程分析》

    https://www.jianshu.com/p/953475cea991

    # Activity啟動過程跟Window的關系?

    建議閱讀:

    《簡析Window、Activity、DecorView以及ViewRoot之間的錯綜關系》

    https://juejin.im/post/5dac6aa2518825630e5d17da

    # ?Activity、Window、ViewRoot和DecorView之間的關系?

    建議閱讀:

    《總結UI原理和高級的UI優化方式》

    https://www.jianshu.com/p/8766babc40e0

    4. Context

    # 關于Context的理解?

    建議閱讀:

    《Android Context 上下文 你必須知道的一切》

    https://blog.csdn.net/lmj623565791/article/details/40481055

    5. 斷點續傳

    # 多線程斷點續傳?

    基礎知識:

    • Http基礎:在Http請求中,可以加入請求頭Range,下載指定區間的文件數。

    • RandomAccessFile:支持隨機訪問,可以從指定位置進行數據的讀寫。

    有了這個基礎以后,思路就清晰了:

  • 通過HttpUrlConnection獲取文件長度。

  • 自己分配好線程進行制定區間的文件數據的下載。

  • 獲取到數據流以后,使用RandomAccessFile進行指定位置的讀寫。

  • 6. 性能優化

    # 平時做了哪些性能優化?

    建議閱讀:

    《Android 性能優化最佳實踐》

    https://juejin.im/post/5b50b017f265da0f7b2f649c

    7. 第三方庫

    一定要在熟練使用后再去查看原理。

    # Glide

    Glide考察的頻率挺高的,常見的問題有:

    • Glide和其他圖片加載框架的比較?

    • 如何設計一個圖片加載框架?

    • Glide緩存實現機制?

    • Glide如何處理生命周期?

    • ...

    建議閱讀:

    《Glide最全解析》

    https://blog.csdn.net/sinyu890807/category_9268670.html

    《面試官:簡歷上最好不要寫Glide,不是問源碼那么簡單》

    https://juejin.im/post/5dbeda27e51d452a161e00c8

    # OkHttp

    OkHttp常見知識點:

    • 責任鏈模式

    • interceptors和networkInterceptors的區別?

    建議看一遍源碼,過程并不復雜。

    # Retrofit

    Retrofit常見問題:

    • 設計模式和封層解耦的理念

    • 動態代理

    建議看一遍源碼,過程并不復雜。

    # RxJava

    RxJava難在各種操作符,我們了解一下大致的設計思想即可。

    建議尋找一些RxJava的文章。

    # Android Jetpack(非必須)

    我主要閱讀了Android Jetpack中以下庫的源碼:

    • Lifecycle:觀察者模式,組件生命周期中發送事件。

    • DataBinding:核心就是利用LiveData或者Observablexxx實現的觀察者模式,對16進制的狀態位更新,之后根據這個狀態位去更新對應的內容。

    • LiveData:觀察者模式,事件的生產消費模型。

    • ViewModel:借用Activty異常銷毀時存儲隱藏Fragment的機制存儲ViewModel,保證數據的生命周期盡可能的延長。

    • Paging:設計思想。

    以后有時間再給大家做源碼分析。

    建議閱讀:

    《Android Jetpack源碼分析系列》

    https://blog.csdn.net/mq2553299/column/info/24151

    三、Java基礎

    Java基礎中考察頻率比較高的是Object、String、面向對象、集合、泛型和反射。

    1. Object

    # equals和==的區別?equals和hashcode的關系?

    • ==:基本類型比較值,引用類型比較地址。

    • equals:默認情況下,equals作為對象中的方法,比較的是地址,不過可以根據業務,修改equals方法。

    equals和hashcode之間的關系:

    默認情況下,equals相等,hashcode必相等,hashcode相等,equals不是必相等。hashcode基于內存地址計算得出,可能會相等,雖然幾率微乎其微。

    2. String

    # String、StringBuffer和StringBuilder的區別?

    • String:String屬于不可變對象,每次修改都會生成新的對象。

    • StringBuilder:可變對象,非多線程安全。

    • StringBuffer:可變對象,多線程安全。

    大部分情況下,效率是:StringBuilder>StringBuffer>String。

    3. 面向對象的特性

    # Java中抽象類和接口的特點?

    共同點:

    • 抽象類和接口都不能生成具體的實例。

    • 都是作為上層使用。

    不同點:

    • 抽象類可以有屬性和成員方法,接口不可以。

    • 一個類只能繼承一個類,但是可以實現多個接口。

    • 抽象類中的變量是普通變量,接口中的變量是靜態變量。

    • 抽象類表達的是is-a的關系,接口表達的是like-a的關系。

    # 關于多態的理解?

    多態是面向對象的三大特性:繼承、封裝和多態之一。

    多態的定義:允許不同類對同一消息做出響應。

    多態存在的條件:

  • 要有繼承。

  • 要有復寫。

  • 父類引用指向子類對象。

  • Java中多態的實現方式:接口實現,繼承父類進行方法重寫,同一個類中的方法重載。

    4. 集合

    # HashMap的特點是什么?HashMap的原理?

    • HashMap的特點:

  • 基于Map接口,存放鍵值對。

  • 允許key/value為空。

  • 非多線程安全。

  • 不保證有序,也不保證使用的過程中順序不會改變。

  • 簡單來講,核心是數組+鏈表/紅黑樹,HashMap的原理就是存鍵值對的時候:

  • 通過鍵的Hash值確定數組的位置。

  • 找到以后,如果該位置無節點,直接存放。

  • 該位置有節點即位置發生沖突,遍歷該節點以及后續的節點,比較key值,相等則覆蓋。

  • 沒有就新增節點,默認使用鏈表,相連節點數超過8的時候,在jdk 1.8中會變成紅黑樹。

  • 如果Hashmap中的數組使用情況超過一定比例,就會擴容,默認擴容兩倍。

  • 當然這是存入的過程,其他過程可以自行查閱。這里需要注意的是:

    • key的hash值計算過程是高16位不變,低16位和高16位取抑或,讓更多位參與進來,可以有效的減少碰撞的發生。

    • 初始數組容量為16,默認不超過的比例為0.75。

    5. 泛型

    # 說一下對泛型的理解?

    泛型的本質是參數化類型,在不創建新的類型的情況下,通過泛型指定不同的類型來控制形參具體限制的類型。也就是說在泛型的使用中,操作的數據類型被指定為一個參數,這種參數可以被用在類、接口和方法中,分別被稱為泛型類、泛型接口和泛型方法。

    泛型是Java中的一種語法糖,能夠在代碼編寫的時候起到類型檢測的作用,但是虛擬機是不支持這些語法的。

    泛型的優點:

  • 類型安全,避免類型的強轉。

  • 提高了代碼的可讀性,不必要等到運行的時候才去強制轉換。

  • # 什么是類型擦除?

    不管泛型的類型傳入哪一種類型實參,對于Java來說,都會被當成同一類處理,在內存中也只占用一塊空間。通俗一點來說,就是泛型只作用于代碼編譯階段,在編譯過程中,對于正確檢驗泛型結果后,會將泛型的信息擦除,也就是說,成功編譯過后的class文件是不包含任何泛型信息的。

    6. 反射

    # 動態代理和靜態代理

    靜態代理很簡單,運用的就是代理模式:

    聲明一個接口,再分別實現一個真實的主題類和代理主題類,通過讓代理類持有真實主題類,從而控制用戶對真實主題的訪問。

    動態代理指的是在運行時動態生成代理類,即代理類的字節碼在運行時生成并載入當前的ClassLoader。

    動態代理的原理是使用反射,思路和上面的一致。

    使用動態代理的好處:

  • 不需要為RealSubject寫一個形式完全一樣的代理類。

  • 使用一些動態代理的方法可以在運行時制定代理類的邏輯,從而提升系統的靈活性。

  • 四、Java并發

    Java并發中考察頻率較高的有線程、線程池、鎖、線程間的等待和喚醒、線程特性和阻塞隊列等。

    1. 線程

    # 線程的狀態有哪些?

    附上一張狀態轉換的圖:

    # 線程中wait和sleep的區別?

    wait方法既釋放cpu,又釋放鎖。
    sleep方法只釋放cpu,但是不釋放鎖。

    # 線程和進程的區別?

    線程是CPU調度的最小單位,一個進程中可以包含多個線程,在Android中,一個進程通常是一個App,App中會有一個主線程,主線程可以用來操作界面元素,如果有耗時的操作,必須開啟子線程執行,不然會出現ANR,除此以外,進程間的數據是獨立的,線程間的數據可以共享。

    2. 線程池

    線程池的地位十分重要,基本上涉及到跨線程的框架都使用到了線程池,比如說OkHttp、RxJava、LiveData以及協程等。

    # 與新建一個線程相比,線程池的特點?

  • 節省開銷:線程池中的線程可以重復利用。

  • 速度快:任務來了就能開始,省去創建線程的時間。

  • 線程可控:線程數量可空和任務可控。

  • 功能強大:可以定時和重復執行任務。

  • # 線程池中的幾個參數是什么意思,線程池的種類有哪些?

    線程池的構造函數如下:

    public?ThreadPoolExecutor(int?corePoolSize,int?maximumPoolSize,long?keepAliveTime,
    ??????????????????????????TimeUnit?unit,
    ??????????????????????????BlockingQueue?workQueue)?{

    參數解釋如下:

    • corePoolSize:核心線程數量,不會釋放。

    • maximumPoolSize:允許使用的最大線程池數量,非核心線程數量,閑置時會釋放。

    • keepAliveTime:閑置線程允許的最大閑置時間。

    • unit:閑置時間的單位。

    • workQueue:阻塞隊列,不同的阻塞隊列有不同的特性。

    線程池分為四個類型:

    • CachedThreadPool:閑置線程超時會釋放,沒有閑置線程的情況下,每次都會創建新的線程。

    • FixedThreadPool:線程池只能存放指定數量的線程池,線程不會釋放,可重復利用。

    • SingleThreadExecutor:單線程的線程池。

    • ScheduledThreadPool:可定時和重復執行的線程池。

    # 線程池的工作流程?

    圖片來自《線程池是怎樣工作的》

    https://www.jianshu.com/p/9de89960ec01

    簡而言之:

  • 任務來了,優先考慮核心線程。

  • 核心線程滿了,進入阻塞隊列。

  • 阻塞隊列滿了,考慮非核心線程(圖上好像少了這個過程)。

  • 非核心線程滿了,再觸發拒絕任務。

  • 3. 鎖

    # 死鎖觸發的四大條件?

  • 互斥鎖

  • 請求與保持

  • 不可剝奪

  • 循環的請求與等待

  • # synchronized關鍵字的使用?synchronized的參數放入對象和Class有什么區別?

    synchronized關鍵字的用法:

    • 修飾方法

    • 修飾代碼塊:需要自己提供鎖對象,鎖對象包括對象本身、對象的Class和其他對象。

    放入對象和Class的區別是:

  • 鎖住的對象不同:成員方法鎖住的實例對象,靜態方法鎖住的是Class。

  • 訪問控制不同:如果鎖住的是實例,只會針對同一個對象方法進行同步訪問,多線程訪問同一個對象的synchronized代碼塊是串行的,訪問不同對象是并行的。如果鎖住的是類,多線程訪問的不管是同一對象還是不同對象的synchronized代碼塊是都是串行的。

  • # synchronized的原理?

    任何一個對象都有一個monitor與之相關聯,JVM基于進入和退出mointor對象來實現代碼塊同步和方法同步,兩者實現細節不同:

    • 代碼塊同步:在編譯字節碼的時候,代碼塊起始的地方插入monitorenter
      指令,異常和代碼塊結束處插入monitorexit指令,線程在執行monitorenter指令的時候嘗試獲取monitor對象的所有權,獲取不到的情況下就是阻塞

    • 方法同步:synchronized方法在method_info結構有AAC_synchronized標記,線程在執行的時候獲取對應的鎖,從而實現同步方法

    # synchronized和Lock的區別?

    主要區別:

  • synchronized是Java中的關鍵字,是Java的內置實現;Lock是Java中的接口。

  • synchronized遇到異常會釋放鎖;Lock需要在發生異常的時候調用成員方法Lock#unlock()方法。

  • synchronized是不可以中斷的,Lock可中斷。

  • synchronized不能去嘗試獲得鎖,沒有獲得鎖就會被阻塞;Lock可以去嘗試獲得鎖,如果未獲得可以嘗試處理其他邏輯。

  • synchronized多線程效率不如Lock,不過Java在1.6以后已經對synchronized進行大量的優化,所以性能上來講,其實差不了多少。

  • # 悲觀鎖和樂觀鎖的舉例?以及它們的相關實現?

    悲觀鎖和樂觀鎖的概念:

    • 悲觀鎖:悲觀鎖會認為,修改共享數據的時候其他線程也會修改數據,因此只在不會受到其他線程干擾的情況下執行。這樣會導致其他有需要鎖的線程掛起,等到持有鎖的線程釋放鎖

    • 樂觀鎖:每次不加鎖,每次直接修改共享數據假設其他線程不會修改,如果發生沖突就直接重試,直到成功為止

    舉例:

    • 悲觀鎖:典型的悲觀鎖是獨占鎖,有synchronized、ReentrantLock。

    • 樂觀鎖:典型的樂觀鎖是CAS,實現CAS的atomic為代表的一系列類

    # CAS是什么?底層原理?

    CAS全稱Compare And Set,核心的三個元素是:內存位置、預期原值和新值,執行CAS的時候,會將內存位置的值與預期原值進行比較,如果一致,就將原值更新為新值,否則就不更新。

    底層原理:是借助CPU底層指令cmpxchg實現原子操作。

    4. 線程間通信

    # notify和notifyAll方法的區別?

    notify隨機喚醒一個線程,notifyAll喚醒所有等待的線程,讓他們競爭鎖。

    # wait/notify和Condition類實現的等待通知有什么區別?

    synchronized與wait/notify結合的等待通知只有一個條件,而Condition類可以實現多個條件等待。

    5. 多線程間的特性

    # 多線程間的有序性、可見性和原子性是什么意思?

    • 原子性:執行一個或者多個操作的時候,要么全部執行,要么都不執行,并且中間過程中不會被打斷。Java中的原子性可以通過獨占鎖和CAS去保證

    • 可見性:指多線程訪問同一個變量的時候,一個線程修改了變量的值,其他線程能夠立刻看得到修改的值。鎖和volatile能夠保證可見性

    • 有序性:程序執行的順序按照代碼先后的順序執行。鎖和volatile能夠保證有序性

    # happens-before原則有哪些?

    Java內存模型具有一些先天的有序性,它通常叫做happens-before原則。

    如果兩個操作的先后順序不能通過happens-before原則推倒出來,那就不能保證它們的先后執行順序,虛擬機就可以隨意打亂執行指令。happens-before原則有:

    • 程序次序規則:單線程程序的執行結果得和看上去代碼執行的結果要一致。

    • 鎖定規則:一個鎖的lock操作一定發生在上一個unlock操作之后。

    • volatile規則:對volatile變量的寫操作一定先行于后面對這個變量的對操作。

    • 傳遞規則:A發生在B前面,B發生在C前面,那么A一定發生在C前面。

    • 線程啟動規則:線程的start方法先行發生于線程中的每個動作。

    • 線程中斷規則:對線程的interrupt操作先行發生于中斷線程的檢測代碼。

    • 線程終結原則:線程中所有的操作都先行發生于線程的終止檢測。

    • 對象終止原則:一個對象的初始化先行發生于他的finalize()方法的執行。

    前四條規則比較重要。

    # volatile的原理?

    可見性

    如果對聲明了volatile的變量進行寫操作的時候,JVM會向處理器發送一條Lock前綴的指令,將這個變量所在緩存行的數據寫入到系統內存。

    多處理器的環境下,其他處理器的緩存還是舊的,為了保證各個處理器一致,會通過嗅探在總線上傳播的數據來檢測自己的數據是否過期,如果過期,會強制重新將系統內存的數據讀取到處理器緩存。

    有序性

    Lock前綴的指令相當于一個內存柵欄,它確保指令排序的時候,不會把后面的指令拍到內存柵欄的前面,也不會把前面的指令排到內存柵欄的后面。

    6. 阻塞隊列

    # 通常的阻塞隊列有哪幾種,特點是什么?

    • ArrayBlockQueue:基于數組實現的有界的FIFO(先進先出)阻塞隊列。

    • LinkedBlockQueue:基于鏈表實現的無界的FIFO(先進先出)阻塞隊列。

    • SynchronousQueue:內部沒有任何緩存的阻塞隊列。

    • PriorityBlockingQueue:具有優先級的無限阻塞隊列。

    # ConcurrentHashMap的原理

    數據結構的實現跟HashMap一樣,不做介紹。

    JDK 1.8之前采用的是分段鎖,核心類是一個Segment,Segment繼承了ReentrantLock,每個Segment對象管理若干個桶,多個線程訪問同一個元素的時候只能去競爭獲取鎖。

    JDK 1.8采用了CAS + synchronized,插入鍵值對的時候如果當前桶中沒有Node節點,使用CAS方式進行更新,如果有Node節點,則使用synchronized的方式進行更新。

    五、網絡

    掌握網絡知識其實是需要一個系統的過程,在時間充裕的情況下,建議還是系統化的學習。

    高頻網絡知識有TCP、HTTP和HTTPS。

    1. HTTP和HTTPS

    # HTTP是哪一層的協議,常見的HTTP狀態碼有哪些,分別代表什么意思?

    HTTP協議是應用層的協議。

    常見的HTTP狀態碼有:

    類別解釋
    1xx請求已經接收,繼續處理
    2xx服務器已經正確處理請求,比如200
    3xx重定向,需要做進一步的處理才能完成請求
    4xx服務器無法理解的請求,比如404,訪問的資源不存在
    5xx服務器收到請求以后,處理錯誤

    # HTTP 1.1 和HTTP 2有什么區別?

    HTTP 2.0基于HTTP 1.1,與HTTP 2.0增加了:

    • 二進制格式:HTTP 1.1使用純文本進行通信,HTTP 2.0使用二進制進行傳輸。

    • Head壓縮:對已經發送的Header使用鍵值建立索引表,相同的Header使用索引表示。

    • 服務器推送:服務器可以進行主動推送

    • 多路復用:一個TCP連接可以劃分成多個流,每個流都會分配Id,客戶端可以借助流和服務端建立全雙工進行通信,并且流具有優先級。

    # HTTP和HTTPS有什么區別?

    簡單來說,HTTP和HTTPS的關系是這樣的

    HTTPS = HTTP + SSL/TLS

    區別如下:

    • HTTP作用于應用層,使用80端口,起始地址是http://,明文傳輸,消息容易被攔截,串改。

    • HTTPS作用域傳輸層,使用443端口,起始地址是https://,需要下載CA證書,傳輸的過程需要加密,安全性高。

    # SSL/TLS的握手過程?

    這里借用《趣談網絡協議》的圖片:

    # HTTPS傳輸過程中是如何處理進行加密的?為什么有對稱加密的情況下仍然需要進行非對稱加密?

    過程和上圖類似,依次獲取證書,公鑰,最后生成對稱加密的鑰匙進行對稱加密。

    對稱加密可以保證加密效率,但是不能解決密鑰傳輸問題;非對稱加密可以解決傳輸問題,但是效率不高。

    2. TCP相關

    # TCP的三次握手過程,為什么需要三次,而不是兩次或者四次?

    只發送兩次,服務端是不知道自己發送的消息能不能被客戶端接收到。


    因為TCP握手是三次,所以此時雙方都已經知道自己發送的消息能夠被對方收到,所以,第四次的發送就顯得多余了。

    # TCP的四次揮手過程?

    大致意思就是:

    • Client:我要斷開連接了

    • Server:我收到你的消息了

    • Server:我也要斷開連接了

    • Client:收到你要斷開連接的消息了

    之后Client等待兩個MSL(數據包在網絡上生存的最長時間),如果服務端沒有回消息就徹底斷開了。

    # TCP和UDP有什么區別?

    • TCP:基于字節流、面向連接、可靠、能夠進行全雙工通信,除此以外,還能進行流量控制和擁塞控制,不過效率略低

    • UDP:基于報文、面向無連接、不可靠,但是傳輸效率高。

    總的來說,TCP適用于傳輸效率要求低,準確性要求高或要求有連接。而UDP適用于對準確性要求較低,傳輸效率要求較高的場景,比如語音通話、直播等。

    # TCP為什么是一種可靠的協議?如何做到流量控制和擁塞控制?

    • TCP可靠:是因為可以做到數據包發送的有序、無差錯和無重復。

    • 流量控制:是通過滑動窗口實現的,因為發送發和接收方消息發送速度和接收速度不一定對等,所以需要一個滑動窗口來平衡處理效率,并且保證沒有差錯和有序的接收數據包。

    • 擁塞控制:慢開始和擁塞避免、快重傳和快恢復算法。這寫算法主要是為了適應網絡中的帶寬而作出的調整。

    六、設計模式

    經常考察的設計模式不多,活學活用即可。

    1. 六大原則

    設計模式的六大原則是:

    • 單一職責:合理分配類和函數的職責

    • 開閉原則:開放擴展,關閉修改

    • 里式替換:繼承

    • 依賴倒置:面向接口

    • 接口隔離:控制接口的粒度

    • 迪米特:一個類應該對其他的類了解最少

    2. 單例模式

    單例模式被問到的幾率很大,通常會問如下幾種問題。

    # 單例的常用寫法有哪幾種?

    懶漢模式

    public?

    該模式的主要問題是每次獲取實例都需要同步,造成不必要的同步開銷。

    DCL模式

    public?

    高并發環境下可能會發生問題。

    靜態內部類單例

    public?

    枚舉單例

    public?

    優點:線程安全和反序列化不會生成新的實例

    # DCL模式會有什么問題?

    對象生成實例的過程中,大概會經過以下過程:

    • 為對象分配內存空間。

    • 初始化對象中的成員變量。

    • 將對象指向分配的內存空間(此時對象就不為null)。

    由于Jvm會優化指令順序,也就是說2和3的順序是不能保證的。在多線程的情況下,當一個線程完成了1、3過程后,當前線程的時間片已用完,這個時候會切換到另一個線程,另一個線程調用這個單例,會使用這個還沒初始化完成的實例。

    解決方法是使用volatile關鍵字:

    public?

    3. 需要關注的設計模式

    重點了解以下的幾種常用的設計模式:

    • 工廠模式和抽象工廠模式:注意他們的區別。

    • 責任鏈模式:View的事件分發和OkHttp的調用過程都使用到了責任鏈模式。

    • 觀察者模式:重要性不言而喻。

    • 代理模式:建議了解一下動態代理。

    4. MVC\MVP\MVVM

    MVC、MVP和MVVM應該是設計模式中考察頻率最高的知識點了,嚴格意義上來說,它們不能算是設計模式,而是框架。

    # MVC、MVP和MVVM是什么?

    • MVC:Model-View-Controller,是一種分層解偶的框架,Model層提供本地數據和網絡請求,View層處理視圖,Controller處理邏輯,存在問題是Controller層和View層的劃分不明顯,Model層和View層的存在耦合。

    • MVP:Model-View-Presenter,是對MVC的升級,Model層和View層與MVC的意思一致,但Model層和View層不再存在耦合,而是通過Presenter層這個橋梁進行交流。

    • MVVM:Model-View-ViewModel,不同于上面的兩個框架,ViewModel持有數據狀態,當數據狀態改變的時候,會自動通知View層進行更新。

    # MVC和MVP的區別是什么?

    MVP是MVC的進一步解耦,簡單來講,在MVC中,View層既可以和Controller層交互,又可以和Model層交互;而在MVP中,View層只能和Presenter層交互,Model層也只能和Presenter層交互,減少了View層和Model層的耦合,更容易定位錯誤的來源。

    # MVVM和MVP的最大區別在哪?

    MVP中的每個方法都需要你去主動調用,它其實是被動的,而MVVM中有數據驅動這個概念,當你的持有的數據狀態發生變更的時候,你的View你可以監聽到這個變化,從而主動去更新,這其實是主動的。

    # ViewModel如何知道View層的生命周期?

    事實上,如果你僅僅使用ViewModel,它是感知不了生命周期,它需要結合LiveData去感知生命周期,如果僅僅使用DataBinding去實現MVVM,它對數據源使用了弱引用,所以一定程度上可以避免內存泄漏的發生。

    七、算法題

    沒什么好說的,Leetcode + 《劍指Offer》,著重記住一些解決問題的思路。

    除此以外,你還得記住一些常用的算法:排序、反轉鏈表、樹的遍歷和手寫LruCache,這些都寫不出來,就尷尬了。

    如果你不想閱讀書籍,可以參考一下這個Github,親眼見證了從3k Star到34k Star,跪了:

    【fucking-algorithm】:

    https://github.com/labuladong/fucking-algorithm

    簡歷中最重要的是項目經歷。

    可能有的同學會說,我天天在公司擰螺絲,根本沒什么東西可寫。

    所以我們在平時的工作中,不應該僅僅滿足于寫一些業務代碼,而應該常常思考:

    • 在結合的業務的情況下,我可以再做一點什么?

    • 對于已經寫完的代碼,我還可以做哪一些優化?

    九、寫在最后

    經常聽到一些同學調侃,Boss不聘、前程堪憂、拉不上鉤,確實,今年的大環境比較嚴峻,但是一些高級崗位仍然稀缺。

    談一下我自己,小廠背景、18年畢業、普通學校,所以,大廠都沒給過面試機會,好在前兩周內推成功了,我也抓住了這次機會,成功獲得了大廠的Offer。

    所以我想表達什么?打鐵還需自身硬,一定是得建立完比較完整的知識體系的前提下,當機會來臨的時候,才能夠穩穩地把握住,希望和大家共勉~

    如果大家還有什么問題,歡迎在下方留言和我討論。

    分享不易,你的點贊是我分享的動力。

    注:因為篇幅太長,文章有所刪減。

    主要參考:

    https://github.com/LRH1993

    本來每一章節開始都是腦圖的,后來我看是在看不清就刪除了,抱著試一試的心態發現作者更新了百度云原圖下載,就又傳了一遍,就放最后吧,算是給堅持到最后的朋友放置的福利,我試了下,湊合能看清。

    如果還是想要更高清的自己下載哈:

    鏈接:https://pan.baidu.com/s/1bUQccZiuLv8EVKImMDziZQ?

    密碼:wyc8


    ●編號684,輸入編號直達本文

    ●輸入m獲取到文章目錄

    推薦↓↓↓

    Java編程

    更多推薦25個技術類公眾微信

    涵蓋:程序人生、算法與數據結構、黑客技術與網絡安全、大數據技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、數據庫、運維等。

    總結

    以上是生活随笔為你收集整理的android bitmap转图片_这是一份面向Android开发者的复习指南的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。