2021-08-20

用什么Map可以保證線程安全,為什么?ConcurrentHashMap為什么能保證線程安全?1.7和1.8原理有什么差異。

JDK用HashTable來(lái)保證線程安全,缺點(diǎn):將整個(gè)Hash表鎖住,性能很低。

ConcurrentHashMap可以保證線程安全,jdk1.7中是采用Segment + HashEntry + ReentrantLock的方式進(jìn)行實(shí)現(xiàn)的,而1.8中放棄了Segment臃腫的設(shè)計(jì),取而代之的是采用Node + CAS + Synchronized來(lái)保證并發(fā)安全進(jìn)行實(shí)現(xiàn)。


有多少種單例模式,枚舉算不算單例,單例模式中不用volatile會(huì)導(dǎo)致什么問(wèn)題?volatile特性是什么?為什么android中不推薦使用枚舉。

單例顧名思義就是程序運(yùn)行中,最多只能有一個(gè)實(shí)例化的對(duì)象

懶漢式、餓漢式的區(qū)別:區(qū)別實(shí)際上體現(xiàn)在加載時(shí)間上,餓漢式是在類加載的時(shí)候就加載;懶漢式是需要用到該實(shí)例時(shí)才加載。使用餓漢式的話,不管你用不用得到這個(gè)實(shí)例,它都會(huì)在類加載的時(shí)候加載;假如我一直沒(méi)使用到這個(gè)實(shí)例,是不是就浪費(fèi)資源了? 使用懶漢式的話,用到時(shí)候才會(huì)去加載,資源的利用上更為合理。

總結(jié):如果確定某個(gè)單例一定會(huì)用上,餓漢式是一種很合適方法;如果不一定會(huì)用的某個(gè)單例,懶漢式是比較合適的方法。

餓漢式 方法1:靜態(tài)變量方式(線程安全)

/*1.將構(gòu)造方法私有化,外部無(wú)法使用new構(gòu)造方法創(chuàng)建實(shí)例*/

private Singleton1() {}

/*2.內(nèi)部創(chuàng)建對(duì)象*/

private static Singleton1 instence = new Singleton1();

/*3.對(duì)外獲取實(shí)例的方法*/

public static Singleton1 getInstence() { return instence; }?

方法2:靜態(tài)代碼塊方式(線程安全)

/*1.將構(gòu)造方法私有化,外部無(wú)法使用new*/

private Singleton2() {}

/*2.內(nèi)部靜態(tài)代碼塊中創(chuàng)建對(duì)象*/

private static Singleton2 instence;

static { instence = new Singleton2(); }

/*3.對(duì)外獲取實(shí)例的方法*/

public static Singleton2 getInstence() { return instence; }

懶漢式

方法1:雙重檢查(線程安全)這個(gè)方法比較常用

/*1.將構(gòu)造方法私有化,外部無(wú)法使用*/

new private Singleton6() {}

/*2.創(chuàng)建類成員變量instence*/

private static volatile Singleton6 instence;

/*3.對(duì)外獲取實(shí)例的方法,雙重判斷*/

public static Singleton6 getInstence() {

????if(instence == null) {

????????synchronized (Singleton6.class){

????????????if (instence == null){

????????????????instence = new Singleton6();

????????????}

????????}

????}

return instence;

}?

方法2:靜態(tài)內(nèi)部類(線程安全)這個(gè)方法比較常用

? /*1.將構(gòu)造方法私有化,外部無(wú)法使用*/

new private Singleton7() {}

/*2.編寫一個(gè)靜態(tài)內(nèi)部類*/

private static class SingletonInstence {

????private static final Singleton7 INSTENCE = new Singleton7();

}

/*3.提供一個(gè)靜態(tài)公有方法,直接返回SingletonInstence*/

public static Singleton7 getInstence() { return SingletonInstence.INSTENCE; }?

方法3:枚舉(線程安全,還可以防止反序列化重新生成的對(duì)象,推薦使用)這個(gè)方法被大佬推薦使用,至于為啥博主暫時(shí)未去了解

public class Singleton8{

}

enum Sing{

insance;

public void method(){}

}

Volatile是Java虛擬機(jī)提供的輕量級(jí)的同步機(jī)制(三大特性)1.保證可見(jiàn)性2.不保證原子性3.有序性(禁止指令重排)

枚舉會(huì)犧牲執(zhí)行的速度和并大幅增加文件體積。這也是性能優(yōu)化中減少OOM的一個(gè)方面。

implementation 和 api的區(qū)別是什么?

implementation可以讓module在編譯時(shí)隱藏自己使用的依賴,減少build時(shí)間,但是在運(yùn)行時(shí)這個(gè)依賴對(duì)所有模塊

是可見(jiàn)的。而api與compile一樣,無(wú)法隱藏自己使用的依賴。

Glide的緩存是怎么設(shè)計(jì)的?為什么要用弱引用

Glide 的緩存可以分為兩種,一種內(nèi)存緩存,一種是硬盤緩存;其中內(nèi)存緩存又包含 弱引用 和 LruCache ;而硬盤緩存就是 DiskLruCache。

為啥要用弱引用

我們知道,glide 是用弱引用緩存當(dāng)前的活躍資源的;為啥不直接從 LruCache 取呢?原因猜測(cè)如下:

這樣可以保護(hù)當(dāng)前使用的資源不會(huì)被 LruCache 算法回收

使用弱引用,即可以緩存正在使用的強(qiáng)引用資源,又不阻礙系統(tǒng)需要回收的無(wú)引用資源。

A 跳轉(zhuǎn)到?B頁(yè)面,兩個(gè)頁(yè)面的生命周期怎么走?什么情況下A的stop()不會(huì)執(zhí)行。

當(dāng)A跳轉(zhuǎn)到B的時(shí)候,A先執(zhí)行onCreate -> onStart -> onResume?->?onPause,然后居然是B再執(zhí)行onCreate -> onStart -> onResume,最后才執(zhí)行A的onStop!!!

當(dāng)B按下返回鍵,B先執(zhí)行onPause,然后居然是A再執(zhí)行onRestart -> onStart -> onResume,最后才是B執(zhí)行onStop? -> onDestroy!!!

原理:A跳轉(zhuǎn)B當(dāng)調(diào)用startActivity時(shí),向當(dāng)前棧中添加activityB, activityA 會(huì)執(zhí)行 onPause,此時(shí) activityA 處于失去焦點(diǎn)但可見(jiàn)的狀態(tài),因?yàn)?activityB 還沒(méi)開(kāi)始繪制,所以activityA不會(huì)回調(diào) onStop方法,接著 activityB 會(huì)開(kāi)始執(zhí)行 onCreate -> onStart -> onResume ,我們都知道Activity 是在 onResume 中開(kāi)始繪制界面,當(dāng) activityB執(zhí)行完 onResume后,此時(shí) activityA 處于不可見(jiàn)的狀態(tài),即按圖上所示,activityA 會(huì)回調(diào) onStop 方法。這也就是在activityA 跳轉(zhuǎn) activityB 時(shí),A的onStop 最后執(zhí)行。B 返回 A同理,在activityB中按下返回鍵,activityB會(huì)先執(zhí)行 onPause ,此時(shí)B還處于可見(jiàn)狀態(tài),A 會(huì)執(zhí)行 onRestart -> onStart -> onResume ->,此時(shí)A 已經(jīng)處于可見(jiàn)狀態(tài)了,B 不可見(jiàn),開(kāi)始執(zhí)行 onStop -> onDestroy 方法。這樣解釋就正確了!?

ActivityB 為 dialog 式或者 半透明背景 ,當(dāng)A跳轉(zhuǎn)到B的時(shí)候,A先執(zhí)行onPause,然后居然是B再執(zhí)行onCreate -> onStart -> onResume。(注意:A的 onStop 不會(huì)執(zhí)行)

當(dāng)B按下返回鍵,B先執(zhí)行onPause,然后是A只會(huì)執(zhí)行 onResume,最后 B 執(zhí)行onStop? -> onDestroy

Activity 的4中啟動(dòng)模式分別是什么,有什么不同。

standard:在Activity的棧中無(wú)論該活動(dòng)有沒(méi)有加入棧,活動(dòng)就會(huì)被創(chuàng)建。

singleTop:只要被創(chuàng)建的活動(dòng)不位于棧的頂部,該活動(dòng)就會(huì)被創(chuàng)建入棧。如果將要被創(chuàng)建的活動(dòng)位于棧的頂部,該活動(dòng)的實(shí)例就不會(huì)被創(chuàng)建。測(cè)試方法,把上面的模式直接改成singleTop模式,MainActivty往自己身上跳轉(zhuǎn)就不會(huì)從新創(chuàng)建一個(gè)新的實(shí)例,會(huì)重用之前在棧頂中的實(shí)例。如果是MainActivty跳轉(zhuǎn)到SecondActivty, 然后SecondActivity再次跳轉(zhuǎn)到MainActivty, 那么此時(shí)的MainActivity將會(huì)被創(chuàng)建,因?yàn)闂m斒荢econdActivity。

singleTask:?jiǎn)稳蝿?wù)模式,這個(gè)也不難理解,如果從MainActivty跳轉(zhuǎn)到SecondActivity, 如果再?gòu)腟econdActivty跳轉(zhuǎn)到MainActivity, 在單任務(wù)模式下MainActivity已經(jīng)在棧中,就會(huì)把它之前的Activity出棧,使其處于在棧頂活躍的位置。

singleInstance:,這個(gè)比較特殊,被設(shè)置成singleInstance的Activity將會(huì)放入另一個(gè)棧中,因?yàn)檫@樣為了便于共用。上面3中模式位于同一個(gè)棧中。下方ThirdActivity跳轉(zhuǎn)到一個(gè)加載模式為singleInstance的Activity中。

GC原理,有哪幾種GC方式

GC垃圾收集,Java提供的GC可以自動(dòng)監(jiān)測(cè)對(duì)象是否超過(guò)作用域從而達(dá)到自動(dòng)回收內(nèi)存的目的。

(1)強(qiáng)引用(Strong Reference):如“Object obj = new Object()”,這類引用是Java程序中最普遍的。只要強(qiáng)引用還存在,垃圾收集器就永遠(yuǎn)不會(huì)回收掉被引用的對(duì)象。

? (2)軟引用(Soft Reference):它用來(lái)描述一些可能還有用,但并非必須的對(duì)象。在系統(tǒng)內(nèi)存不夠用時(shí),這類引用關(guān)聯(lián)的對(duì)象將被垃圾收集器回收。JDK1.2之后提供了SoftReference類來(lái)實(shí)現(xiàn)軟引用。

? (3)弱引用(Weak Reference):它也是用來(lái)描述非須對(duì)象的,但它的強(qiáng)度比軟引用更弱些,被弱引用關(guān)聯(lián)的對(duì)象只能生存到下一次垃圾收集發(fā)生之前。當(dāng)垃圾收集器工作時(shí),無(wú)論當(dāng)前內(nèi)存是否足夠,都會(huì)回收掉只被弱引用關(guān)聯(lián)的對(duì)象。在JDK1.2之后,提供了WeakReference類來(lái)實(shí)現(xiàn)弱引用。

? (4)虛引用(Phantom Reference):最弱的一種引用關(guān)系,完全不會(huì)對(duì)其生存時(shí)間構(gòu)成影響,也無(wú)法通過(guò)虛引用來(lái)取得一個(gè)對(duì)象實(shí)例。為一個(gè)對(duì)象設(shè)置虛引用關(guān)聯(lián)的唯一目的是希望能在這個(gè)對(duì)象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知。JDK1.2之后提供了PhantomReference類來(lái)實(shí)現(xiàn)虛引用。

在 Java 中,堆被劃分成兩個(gè)不同的區(qū)域:新生代 ( Young )、老年代 ( Old ),新生代默認(rèn)占總空間的 1/3,老年代默認(rèn)占 2/3。

新生代有 3 個(gè)分區(qū):Eden、To Survivor、From Survivor,它們的默認(rèn)占比是 8:1:1。

新生代的垃圾回收(又稱Minor GC)后只有少量對(duì)象存活,所以選用復(fù)制算法,只需要少量的復(fù)制成本就可以完成回收。

老年代的垃圾回收(又稱Major GC)通常使用“標(biāo)記-清理”或“標(biāo)記-整理”算法。

再描述它們之間轉(zhuǎn)化流程:

對(duì)象優(yōu)先在Eden分配。當(dāng) eden 區(qū)沒(méi)有足夠空間進(jìn)行分配時(shí),虛擬機(jī)將發(fā)起一次 Minor GC。

在 Eden 區(qū)執(zhí)行了第一次 GC 之后,存活的對(duì)象會(huì)被移動(dòng)到其中一個(gè) Survivor 分區(qū);

Eden 區(qū)再次 GC,這時(shí)會(huì)采用復(fù)制算法,將 Eden 和 from 區(qū)一起清理,存活的對(duì)象會(huì)被復(fù)制到 to 區(qū);

移動(dòng)一次,對(duì)象年齡加 1,對(duì)象年齡大于一定閥值會(huì)直接移動(dòng)到老年代。GC年齡的閥值可以通過(guò)參數(shù) -XX:MaxTenuringThreshold 設(shè)置,默認(rèn)為 15;

動(dòng)態(tài)對(duì)象年齡判定:Survivor 區(qū)相同年齡所有對(duì)象大小的總和 > (Survivor 區(qū)內(nèi)存大小 * 這個(gè)目標(biāo)使用率)時(shí),大于或等于該年齡的對(duì)象直接進(jìn)入老年代。其中這個(gè)使用率通過(guò) -XX:TargetSurvivorRatio 指定,默認(rèn)為 50%;

Survivor 區(qū)內(nèi)存不足會(huì)發(fā)生擔(dān)保分配,超過(guò)指定大小的對(duì)象可以直接進(jìn)入老年代。

大對(duì)象直接進(jìn)入老年代,大對(duì)象就是需要大量連續(xù)內(nèi)存空間的對(duì)象(比如:字符串、數(shù)組),為了避免為大對(duì)象分配內(nèi)存時(shí)由于分配擔(dān)保機(jī)制帶來(lái)的復(fù)制而降低效率。

老年代滿了而無(wú)法容納更多的對(duì)象,Minor GC 之后通常就會(huì)進(jìn)行Full GC,F(xiàn)ull GC 清理整個(gè)內(nèi)存堆 –包括年輕代和老年代

Android包體積優(yōu)化方案

1.對(duì)dex文件進(jìn)行優(yōu)化,減少無(wú)用代碼,減少java,aidl文件

2.對(duì)資源文件進(jìn)行優(yōu)化

3.添加混淆

事件分發(fā)機(jī)制

用戶觸摸屏幕的時(shí)候,會(huì)觸發(fā)Touch事件。主要發(fā)生的Touch事件有如下四種:

MotionEvent.ACTION_DOWN:按下View(所有事件的開(kāi)始)

MotionEvent.ACTION_MOVE:滑動(dòng)View

MotionEvent.ACTION_CANCEL:非人為原因結(jié)束本次事件

MotionEvent.ACTION_UP:抬起View(與DOWN對(duì)應(yīng))

即當(dāng)一個(gè)MotionEvent 產(chǎn)生后,系統(tǒng)需要把這個(gè)事件傳遞給一個(gè)具體的 View 去處理,

事件分發(fā)的本質(zhì)是將點(diǎn)擊事件(MotionEvent)向某個(gè)View進(jìn)行傳遞并最終得到處理

即當(dāng)一個(gè)點(diǎn)擊事件發(fā)生后,系統(tǒng)需要將這個(gè)事件傳遞給一個(gè)具體的View去處理。這個(gè)事件傳遞的過(guò)程就是分發(fā)過(guò)程。

一個(gè)點(diǎn)擊事件產(chǎn)生后,傳遞順序是:Activity(Window) -> ViewGroup -> View

事件分發(fā)過(guò)程由dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()三個(gè)方法協(xié)助完成

其中:

super:調(diào)用父類方法

true:消費(fèi)事件,即事件不繼續(xù)往下傳遞

false:不消費(fèi)事件,事件也不繼續(xù)往下傳遞 / 交由給父控件onTouchEvent()處理

方法詳細(xì)介紹
事件分發(fā)機(jī)制詳細(xì)流程

默認(rèn)情況

即不對(duì)控件里的方法(dispatchTouchEvent()、onTouchEvent()、onInterceptTouchEvent())進(jìn)行重寫或更改返回值

那么調(diào)用的是這3個(gè)方法的默認(rèn)實(shí)現(xiàn):調(diào)用父類的方法

事件傳遞情況:(如圖下所示)

從Activity A---->ViewGroup B--->View C,從上往下調(diào)用dispatchTouchEvent()

再由View C--->ViewGroup B --->Activity A,從下往上調(diào)用onTouchEvent()

說(shuō)說(shuō)對(duì)稱加密和非對(duì)稱加密

簡(jiǎn)介: 對(duì)稱加密: 加密和解密的秘鑰使用的是同一個(gè).

非對(duì)稱加密: 與對(duì)稱加密算法不同,非對(duì)稱加密算法需要兩個(gè)密鑰:公開(kāi)密鑰(publickey)和私有密鑰(privatekey)。

對(duì)稱加密算法: 密鑰較短,破譯困難,除了數(shù)據(jù)加密標(biāo)準(zhǔn)(DES),另一個(gè)對(duì)稱密鑰加密系統(tǒng)是國(guó)際數(shù)據(jù)加密算法(IDEA),它比DES的加密性好,且對(duì)計(jì)算機(jī)性能要求也沒(méi)有那么高.

優(yōu)點(diǎn): 算法公開(kāi)、計(jì)算量小、加密速度快、加密效率高

缺點(diǎn): 在數(shù)據(jù)傳送前,發(fā)送方和接收方必須商定好秘鑰,然后 使雙方都能保存好秘鑰。其次如果一方的秘鑰被泄露,那么加密信息也就不安全了。另外,每對(duì)用戶每次使用對(duì)稱加密算法時(shí),都需要使用其他人不知道的唯一秘鑰,這會(huì)使得收、發(fā)雙方所擁有的鑰匙數(shù)量巨大,密鑰管理成為雙方的負(fù)擔(dān)。 常見(jiàn)的對(duì)稱加密算法有: DES、3DES、Blowfish、IDEA、RC4、RC5、RC6 和 AES

非對(duì)稱加密算法: 公開(kāi)密鑰與私有密鑰是一對(duì),如果用公開(kāi)密鑰對(duì)數(shù)據(jù)進(jìn)行加密,只有用對(duì)應(yīng)的私有密鑰才能解密;如果用私有密鑰對(duì)數(shù)據(jù)進(jìn)行加密,那么只有用對(duì)應(yīng)的公開(kāi)密鑰才能解密。因?yàn)榧用芎徒饷苁褂玫氖莾蓚€(gè)不同的密鑰,所以這種算法叫作非對(duì)稱加密算法。

非對(duì)稱加密算法實(shí)現(xiàn)機(jī)密信息交換的基本過(guò)程是:甲方生成一對(duì)密鑰并將其中的一把作為公用密鑰向其它方公開(kāi);得到該公用密鑰的乙方使用該密鑰對(duì)機(jī)密信息進(jìn)行加密后再發(fā)送給甲方;甲方再用自己保存的另一把專用密鑰對(duì)加密后的信息進(jìn)行解密。甲方只能用其專用密鑰解密由其公用密鑰加密后的任何信息。

優(yōu)點(diǎn): 安全

缺點(diǎn): 速度較慢 常見(jiàn)的非對(duì)稱加密算法有: RSA、ECC(移動(dòng)設(shè)備用)、Diffie-Hellman、El Gamal、DSA(數(shù)字簽名用)

鎖有哪些

從線程是否需要對(duì)資源加鎖可以分為 悲觀鎖 和 樂(lè)觀鎖

從資源已被鎖定,線程是否阻塞可以分為 自旋鎖

從多個(gè)線程并發(fā)訪問(wèn)資源,也就是 Synchronized 可以分為 無(wú)鎖、偏向鎖、 輕量級(jí)鎖 和 重量級(jí)鎖

從鎖的公平性進(jìn)行區(qū)分,可以分為公平鎖 和 非公平鎖

從根據(jù)鎖是否重復(fù)獲取可以分為 可重入鎖 和 不可重入鎖

從那個(gè)多個(gè)線程能否獲取同一把鎖分為 共享鎖 和 排他鎖

一文足以了解什么是 Java 中的鎖 (baidu.com)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android中高級(jí)面試題 1、Activity生命周期? onCreate() -> onStart() -> ...
    司文喰閱讀 588評(píng)論 0 0
  • 1、Handler: 1):系統(tǒng)Handler的創(chuàng)建過(guò)程及相關(guān)對(duì)象的創(chuàng)建:在ActivityThread的main...
    Steven_SHH閱讀 1,006評(píng)論 0 5
  • 緩存 memcache的分布式原理 memcached 雖然稱為 “ 分布式 ” 緩存服務(wù)器,但服務(wù)器端并沒(méi)有 “...
    元?dú)廛浖?/span>閱讀 453評(píng)論 0 0
  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,755評(píng)論 11 349
  • Java面試題 GC機(jī)制 垃圾回收需要完成兩件事:找到垃圾,回收垃圾。找到垃圾一般的話有兩種方法: 引用計(jì)數(shù)法 當(dāng)...
    hackest閱讀 1,248評(píng)論 3 14

友情鏈接更多精彩內(nèi)容