Object 類相關(guān)方法
?
getClass 獲取當(dāng)前運(yùn)行時(shí)對象的 Class 對象。
hashCode 返回對象的 hash 碼。
clone 拷貝當(dāng)前對象, 必須實(shí)現(xiàn) Cloneable 接口。淺拷貝對基本類型進(jìn)行值拷貝,對引用類型拷貝引用;深拷貝對基本類型進(jìn)行值拷貝,對引用類型對象不但拷貝對象的引用還拷貝對象的相關(guān)屬性和方法。兩者不同在于深拷貝創(chuàng)建了一個(gè)新的對象。
equals 通過內(nèi)存地址比較兩個(gè)對象是否相等,String 類重寫了這個(gè)方法使用值來比較是否相等。
toString 返回類名@哈希碼的 16 進(jìn)制。
notify 喚醒當(dāng)前對象監(jiān)視器的任一個(gè)線程。
notifyAll 喚醒當(dāng)前對象監(jiān)視器上的所有線程。
wait 1、暫停線程的執(zhí)行;2、三個(gè)不同參數(shù)方法(等待多少毫秒;額外等待多少毫秒;一直等待)3、與 Thread.sleep(long time) 相比,sleep 使當(dāng)前線程休眠一段時(shí)間,并沒有釋放該對象的鎖,wait 釋放了鎖。
finalize 對象被垃圾回收器回收時(shí)執(zhí)行的方法。
2、基本數(shù)據(jù)類型
整型:byte(8)、short(16)、int(32)、long(64)
浮點(diǎn)型:float(32)、double(64)
布爾型:boolean(8)
字符型:char(16)
3、序列化
Java 對象實(shí)現(xiàn)序列化要實(shí)現(xiàn) Serializable 接口。
?
反序列化并不會(huì)調(diào)用構(gòu)造方法。反序列的對象是由 JVM 自己生成的對象,不通過構(gòu)造方法生成。
序列化對象的引用類型成員變量,也必須是可序列化的,否則,會(huì)報(bào)錯(cuò)。
如果想讓某個(gè)變量不被序列化,使用 transient 修飾。
單例類序列化,需要重寫 readResolve() 方法。
4、String、StringBuffer、StringBuilder
String 由 char[] 數(shù)組構(gòu)成,使用了 final 修飾,是不可變對象,可以理解為常量,線程安全;對 String 進(jìn)行改變時(shí)每次都會(huì)新生成一個(gè) String 對象,然后把指針指向新的引用對象。
StringBuffer 線程安全;StringBuiler 線程不安全。
操作少量字符數(shù)據(jù)用 String;單線程操作大量數(shù)據(jù)用 StringBuilder;多線程操作大量數(shù)據(jù)用 StringBuffer。
5、重載與重寫
重載 發(fā)生在同一個(gè)類中,方法名相同,參數(shù)的類型、個(gè)數(shù)、順序不同,方法的返回值和修飾符可以不同。
重寫 發(fā)生在父子類中,方法名和參數(shù)相同,返回值范圍小于等于父類,拋出的異常范圍小于等于父類,訪問修飾符范圍大于等于父類;如果父類方法訪問修飾符為 private 或者 final 則子類就不能重寫該方法。
6、final
修飾基本類型變量,一經(jīng)出初始化后就不能夠?qū)ζ溥M(jìn)行修改。
修飾引用類型變量,不能夠指向另一個(gè)引用。
修飾類或方法,不能被繼承或重寫。
7、反射
在運(yùn)行時(shí)動(dòng)態(tài)的獲取類的完整信息
增加程序的靈活性
JDK 動(dòng)態(tài)代理使用了反射
8、JDK 動(dòng)態(tài)代理
使用步驟
創(chuàng)建接口及實(shí)現(xiàn)類
實(shí)現(xiàn)代理處理器:實(shí)現(xiàn) InvokationHandler ,實(shí)現(xiàn) invoke(Proxy proxy,Method method,Object[] args) 方法
通過 Proxy.newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h) 獲得代理類
通過代理類調(diào)用方法。
9、Java IO
普通 IO ,面向流,同步阻塞線程。
NIO,面向緩沖區(qū),同步非阻塞。
二、Java 集合框架
1、List(線性結(jié)構(gòu))
ArrayList Object[] 數(shù)組實(shí)現(xiàn),默認(rèn)大小為 10 ,支持隨機(jī)訪問,連續(xù)內(nèi)存空間,插入末尾時(shí)間復(fù)雜度 o(1),插入第 i 個(gè)位置時(shí)間復(fù)雜度 o(n - i)。擴(kuò)容,大小變?yōu)?1.5 倍,Arrays.copyOf(底層 System.ArrayCopy),復(fù)制到新數(shù)組,指針指向新數(shù)組。
Vector 類似 ArrayList,線程安全,擴(kuò)容默認(rèn)增長為原來的 2 倍,還可以指定增長空間長度。
LinkedList 基于鏈表實(shí)現(xiàn),1.7 為雙向鏈表,1.6 為雙向循環(huán)鏈表,取消循環(huán)更能分清頭尾。
2、Map(K,V 對)
HashMap
底層數(shù)據(jù)結(jié)構(gòu),JDK 1.8 是數(shù)組 + 鏈表 + 紅黑樹,JDK 1.7 無紅黑樹。鏈表長度大于 8 時(shí),轉(zhuǎn)化為紅黑樹,優(yōu)化查詢效率。
初始容量為 16,通過 tableSizeFor 保證容量為 2 的冪次方。尋址方式,高位異或,(n-1)&h 取模,優(yōu)化速度。
擴(kuò)容機(jī)制,當(dāng)元素?cái)?shù)量大于容量 x 負(fù)載因子 0.75 時(shí),容量擴(kuò)大為原來的 2 倍,新建一個(gè)數(shù)組,然后轉(zhuǎn)移到新數(shù)組。
基于 Map 實(shí)現(xiàn)。
線程不安全。
HashMap (1.7) 多線程循環(huán)鏈表問題
在多線程環(huán)境下,進(jìn)行擴(kuò)容時(shí),1.7 下的 HashMap 會(huì)形成循環(huán)鏈表。
怎么形成循環(huán)鏈表: 假設(shè)有一 HashMap 容量為 2 , 在數(shù)組下標(biāo) 1 位置以 A -> B 鏈表形式存儲(chǔ)。有一線程對該 map 做 put 操作,由于觸發(fā)擴(kuò)容條件,需要進(jìn)行擴(kuò)容。這時(shí)另一個(gè)線程也 put 操作,同樣需要擴(kuò)容,并完成了擴(kuò)容操作,由于復(fù)制到新數(shù)組是頭部插入,所以 1 位置變?yōu)?B -> A 。這時(shí)第一個(gè)線程繼續(xù)做擴(kuò)容操作,首先復(fù)制 A ,然后復(fù)制 B ,再判斷 B.next 是否為空時(shí),由于第二個(gè)線程做了擴(kuò)容操作,導(dǎo)致 B.next = A,所以在將 A 放到 B 前,A.next 又等于 B ,導(dǎo)致循環(huán)鏈表出現(xiàn)。
HashTable
線程安全,方法基本全用 Synchronized 修飾。
初始容量為 11 ,擴(kuò)容為 2n + 1 。
繼承 Dictionary 類。
ConcurrentHashMap
線程安全的 HashMap。
1.7 采用分段鎖的形式加鎖;1.8 使用 Synchronized 和 CAS 實(shí)現(xiàn)同步,若數(shù)組的 Node 為空,則通過 CAS 的方式設(shè)置值,不為空則加在鏈表的第一個(gè)節(jié)點(diǎn)。獲取第一個(gè)元素是否為空使用 Unsafe 類提供的 getObjectVolatile 保證可見性。
對于讀操作,數(shù)組由 volatile 修飾,同時(shí)數(shù)組的元素為 Node,Node 的 K 使用 final 修飾,V 使用 volatile 修飾,下一個(gè)節(jié)點(diǎn)也用 volatile 修飾,保證多線程的可見性。
LinkedHashMap LinkedHashMap 繼承自 HashMap,所以它的底層仍然是基于拉鏈?zhǔn)缴⒘薪Y(jié)構(gòu)即由數(shù)組和鏈表或紅黑樹組成。另外,LinkedHashMap 在上面結(jié)構(gòu)的基礎(chǔ)上,增加了一條雙向鏈表,使得上面的結(jié)構(gòu)可以保持鍵值對的插入順序。
TreeMap 有序的 Map,紅黑樹結(jié)構(gòu),可以自定義比較器來進(jìn)行排序。
Collections.synchronizedMap 如何實(shí)現(xiàn) Map 線程安全? 基于 Synchronized ,實(shí)際上就是鎖住了當(dāng)前傳入的 Map 對象。
3、Set(唯一值)
HashSet 基于 HashMap 實(shí)現(xiàn),使用了 HashMap 的 K 作為元素存儲(chǔ),V 為 new Object() ,在 add() 方法中如果兩個(gè)元素的 Hash 值相同,則通過 equals 方法比較是否相等。
LinkedHashSet LinkedHashSet 繼承于 HashSet,并且其內(nèi)部是通過 LinkedHashMap 來實(shí)現(xiàn)的。
TreeSet 紅黑樹實(shí)現(xiàn)有序唯一。
三、Java 多線程
1、synchronized
修飾代碼塊 底層實(shí)現(xiàn),通過 monitorenter & monitorexit 標(biāo)志代碼塊為同步代碼塊。
修飾方法 底層實(shí)現(xiàn),通過 ACC_SYNCHRONIZED 標(biāo)志方法是同步方法。
修飾類 class 對象時(shí),實(shí)際鎖在類的實(shí)例上面。
單例模式
public class Singleton {
?
private static volatile Singleton instance = null;
?
private Singleton(){}
?
public static Singleton getInstance(){
if (null == instance) {
? ? synchronized (Singleton.class) {
? ? ? ? if (null == instance) {
? ? ? ? instance = new Singleton();
? ? ? ? }
? ? }
? }
? ? return instance;
? ? }
?
?
?
?
}
private static volatile Singleton instance = null;
?
private Singleton(){}
?
public static Singleton getInstance(){
if (null == instance) {
? ? synchronized (Singleton.class) {
? ? ? ? if (null == instance) {
? ? ? ? instance = new Singleton();
? ? ? ? }
? ? }
? }
? ? return instance;
? ? }
偏向鎖,自旋鎖,輕量級(jí)鎖,重量級(jí)鎖
通過 synchronized 加鎖,第一個(gè)線程獲取的鎖為偏向鎖,這時(shí)有其他線程參與鎖競爭,升級(jí)為輕量級(jí)鎖,其他線程通過循環(huán)的方式嘗試獲得鎖,稱自旋鎖。若果自旋的次數(shù)達(dá)到一定的閾值,則升級(jí)為重量級(jí)鎖。
需要注意的是,在第二個(gè)線程獲取鎖時(shí),會(huì)先判斷第一個(gè)線程是否仍然存活,如果不存活,不會(huì)升級(jí)為輕量級(jí)鎖。
2、Lock
ReentrantLock
基于 AQS (AbstractQueuedSynchronizer)實(shí)現(xiàn),主要有 state (資源) + FIFO (線程等待隊(duì)列) 組成。
公平鎖與非公平鎖:區(qū)別在于在獲取鎖時(shí),公平鎖會(huì)判斷當(dāng)前隊(duì)列是否有正在等待的線程,如果有則進(jìn)行排隊(duì)。
使用 lock() 和 unLock() 方法來加鎖解鎖。
ReentrantReadWriteLock
同樣基于 AQS 實(shí)現(xiàn),內(nèi)部采用內(nèi)部類的形式實(shí)現(xiàn)了讀鎖(共享鎖)和寫鎖 (排它鎖)。
非公平鎖吞吐量高 在獲取鎖的階段來分析,當(dāng)某一線程要獲取鎖時(shí),非公平鎖可以直接嘗試獲取鎖,而不是判斷當(dāng)前隊(duì)列中是否有線程在等待。一定情況下可以避免線程頻繁的上下文切換,這樣,活躍的線程有可能獲得鎖,而在隊(duì)列中的鎖還要進(jìn)行喚醒才能繼續(xù)嘗試獲取鎖,而且線程的執(zhí)行順序一般來說不影響程序的運(yùn)行。
3、volatile
Java 內(nèi)存模型
image.png
?
在多線程環(huán)境下,保證變量的可見性。使用了 volatile 修飾變量后,在變量修改后會(huì)立即同步到主存中,每次用這個(gè)變量前會(huì)從主存刷新。
禁止 JVM 指令重排序。文章來源:http://www.zghlxwxcb.cn/news/detail-647564.html
單例模式雙重校驗(yàn)鎖變量為什么使用 volatile 修飾? 禁止 JVM 指令重排序,new Object()分為三個(gè)步驟:申請內(nèi)存空間,將內(nèi)存空間引用賦值給變量,變量初始化。如果不禁止重排序,有可能得到一個(gè)未經(jīng)初始化的變文章來源地址http://www.zghlxwxcb.cn/news/detail-647564.html
到了這里,關(guān)于Java 基礎(chǔ)知識(shí)點(diǎn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!