
7f670aa6198e7af7bc8e4d11623154bc.jpeg
1.HashMap 1.7,1.8的差異,1.8中什么情況下轉(zhuǎn)換為紅黑樹,構(gòu)造函數(shù)中參數(shù)代表的意思?
1. JDK1.7用的是頭插法,而JDK1.8及之后使用的都是尾插法。
2.擴容后數(shù)據(jù)存儲位置的計算方式也不一樣。
3. JDK1.7的時候使用的是數(shù)組+ 單鏈表的數(shù)據(jù)結(jié)構(gòu)。
JDK1.8及之后時,使用的是數(shù)組+鏈表+紅黑樹的數(shù)據(jù)結(jié)構(gòu)。
---
JDK1.8以后的hashmap鏈表長度為8才轉(zhuǎn)變?yōu)榧t黑樹。
---
有兩個參數(shù)的構(gòu)造方法HashMap(int initialCapacity, float loadFactor)
參數(shù):initialCapacity 初始容量
參數(shù):loadFactor 負載因子
2.用什么Map可以保證線程安全,為什么?ConcurrentHashMap為什么能保證線程安全?1.7和1.8原理有什么差異。
ConcurrentHashMap
---
ConcurrentHashMap是把表進行分段,
初始情況下分成16段,每一段都有一把鎖,
當多個線程訪問不同的段時,因為獲取到的鎖是不同的,
所以可以并行的訪問。
效率比Hashtable高多了,推薦使用。
---
jdk1.7的結(jié)構(gòu)是數(shù)組+鏈表組成的
jdk1.8的ConcurrentHashMap拋棄了原有的Segment分段鎖,
而采用了 CAS + synchronized 來保證并發(fā)安全性。
底層結(jié)構(gòu)也采用了數(shù)組+鏈表+紅黑數(shù)的結(jié)構(gòu)。
3.有多少種單例模式,枚舉算不算單例,單例模式中不用volatile會導(dǎo)致什么問題?volatile特性是什么?為什么android中不推薦使用枚舉。
懶漢式、餓漢式
---
算,最佳的單例實現(xiàn)模式就是枚舉模式
---
不用volatile會導(dǎo)致線程不安全
---
volatile關(guān)鍵字的特性
可見性:此變量對所有線程可見,當一個線程修改了這個變量的值,新值對其他線程是可以立即得知的。
禁止指令重排序優(yōu)化:普通的變量僅會保證該方法的執(zhí)行過程中所有依賴賦值結(jié)果的地方都能獲取到正確的結(jié)果,而不能保證變量賦值操作的順序與程序代碼中的執(zhí)行順序一致。
---
相比較的話使用enum(枚舉)會更加浪費內(nèi)存,
會犧牲執(zhí)行的速度、大幅增加文件體積。
這也是性能優(yōu)化中減少OOM的一個方面。
4.反向輸出字符串。
使用StringBuffer或StringBuilder進行反轉(zhuǎn)。
String str = "dasgfdsfsd";
StringBuffer buf = new StringBuffer(str);
buf = buf.reverse();
System.out.println(buf.toString());
5.兩個有序鏈表合并。
遞歸
非遞歸
6.字符串移除多余空格,且技術(shù)單詞首字符大寫。
str.replace(" ", "");
str.substring(0, 1).toUpperCase()+str.substring(1);
7.二叉樹中和為某一值的路徑。
待解決
8.二進制低位轉(zhuǎn)高位。
9.字符串數(shù)組判重。
10.二叉樹 判斷是否為搜索二叉樹。
11.thread wait sleep join 有什么區(qū)別
1. Thread.sleep()
使當前所在線程進入阻塞
只是讓出CPU,并沒有釋放鎖
由于睡眠時間結(jié)束后不一定立即被CPU調(diào)度,因此線程休眠的時間可能大于傳入的參數(shù)
如果被終端則拋出InterruptedException
2. Object.wait()
讓出CPU,釋放對象鎖
在調(diào)用前需要先擁有對象鎖,所以一般在synchronized中同步塊使用
使該線程進入該對象的監(jiān)視器的等待隊列
3. Thread.join()
join=synchronized+Object.wait();
線程合并,調(diào)用線程會進入阻塞狀態(tài),需要等待被調(diào)用線程結(jié)束后才可以執(zhí)行
應(yīng)用場景:當一個線程必須等待其他線程執(zhí)行完畢才能繼續(xù)執(zhí)行
12.final修飾符
修飾變量:final變量無法被改變,一旦被賦初始值就無法重新賦值。
修飾方法:final方法不能被子類重寫,但能夠被重載。
修飾類:final類無法被繼承。
13.抽象類和接口
1.抽象類可以有構(gòu)造方法,接口中不能有構(gòu)造方法。
2.抽象類中可以有普通成員變量,接口中沒有普通成員變量
3.抽象類中可以包含非抽象的普通方法,接口中的所有方法必須都是抽象的,不能有非抽象的普通方法。
4. 抽象類中的抽象方法的訪問類型可以是public,protected,但接口中的抽象方法只能是public類型的,并且默認即為public abstract類型。
5. 抽象類中可以包含靜態(tài)方法,接口中不能包含靜態(tài)方法
6. 抽象類和接口中都可以包含靜態(tài)成員變量,抽象類中的靜態(tài)成員變量的訪問類型可以任意,但接口中定義的變量只能是public static final類型,并且默認即為public static final類型。
7. 一個類可以實現(xiàn)多個接口,但只能繼承一個抽象類。
14.GC機制、原理;垃圾收集算法;GCRoots有哪些;
GC如其名,就是垃圾收集,當然這里僅就內(nèi)存而言。Garbage Collector(垃圾收集器)以應(yīng)用程序的root為基礎(chǔ),
遍歷應(yīng)用程序在Heap上動態(tài)分配的所有對象,通過識別它們是否被引用來確定哪些對象是已經(jīng)死亡的、哪些仍需要被使用。
已經(jīng)不再被應(yīng)用程序的root或者別的對象所引用的對象就是已經(jīng)死亡的對象,即所謂的垃圾,需要被回收(回收的是該對象占用的內(nèi)存空間)。
這就是GC工作的原理。
---
為了實現(xiàn)這個原理,GC有多種算法。比較常見的算法有
Reference Counting,Mark Sweep,Copy Collection等等。
---
目前主流的虛擬系統(tǒng).NET CLR,Java VM和Rotor都是采用的Mark Sweep算法。
---GCRoots是垃圾回收的起點
虛擬機棧(棧幀中的本地變量表)中引用的對象
方法區(qū)中類靜態(tài)屬性引用的對象
方法區(qū)中常量引用的對象
本地方法棧中JNI(即一般說的native方法)中引用的對象
15.四種引用類型
強引用:Java中默認聲明的就是強引用
軟引用:在內(nèi)存足夠的時候,軟引用對象不會被回收,只有在內(nèi)存不足時,
系統(tǒng)則會回收軟引用對象,如果回收了軟引用對象之后仍然沒有足夠的內(nèi)存,
才會拋出內(nèi)存溢出異常。
弱引用:無論內(nèi)存是否足夠,只要 JVM 開始進行垃圾回收,那些被弱引用關(guān)聯(lián)的對象都會被回收。
虛引用:虛引用是最弱的一種引用關(guān)系,如果一個對象僅持有虛引用,那么它就和沒有任何引用一樣,它隨時可能會被回收
16.線程同步的幾種方式;加鎖與synchromized區(qū)別
1.同步方法:即有synchronized關(guān)鍵字修飾的方法。
2.同步代碼塊 :即有synchronized關(guān)鍵字修飾的語句塊。
3.使用特殊域變量(volatile)實現(xiàn)線程同步
4.使用重入鎖實現(xiàn)線程同步