1.死鎖
死鎖是指兩個(gè)或兩個(gè)以上的線程在執(zhí)行過(guò)程中,由于競(jìng)爭(zhēng)資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去。此時(shí)稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱為死鎖進(jìn)程
-
條件:
1.互斥條件:進(jìn)程對(duì)于所分配到的資源具有排它性,即一個(gè)資源只能被一個(gè)進(jìn)程占用,直到被該進(jìn)程釋放
2.請(qǐng)求和保持條件:一個(gè)進(jìn)程因請(qǐng)求被占用資源而發(fā)生阻塞時(shí),對(duì)已獲得的資源保持不放。
3.不剝奪條件:任何一個(gè)資源在沒(méi)被該進(jìn)程釋放之前,任何其他進(jìn)程都無(wú)法對(duì)他剝奪占用
4.循環(huán)等待條件:當(dāng)發(fā)生死鎖時(shí),所等待的進(jìn)程必定會(huì)形成一個(gè)環(huán)路(類似于死循環(huán)),造成永久阻塞。 -
避免
死鎖避免的基本思想:系統(tǒng)對(duì)進(jìn)程發(fā)出每一個(gè)系統(tǒng)能夠滿足的資源申請(qǐng)進(jìn)行動(dòng)態(tài)檢查,并根據(jù)檢查結(jié)果決定是否分配資源,如果分配后系統(tǒng)可能發(fā)生死鎖,則不予分配,否則予以分配。這是一種保證系統(tǒng)不進(jìn)入死鎖狀態(tài)的動(dòng)態(tài)策略打破互斥條件:改造獨(dú)占性資源為虛擬資源,大部分資源已無(wú)法改造。
打破不可搶占條件:當(dāng)一進(jìn)程占有一獨(dú)占性資源后又申請(qǐng)一獨(dú)占性資源而無(wú)法滿足,則退出原占有的資源。
打破占有且申請(qǐng)條件:采用資源預(yù)先分配策略,即進(jìn)程運(yùn)行前申請(qǐng)全部資源,滿足則運(yùn)行,不然就等待,這樣就不會(huì)占有且申請(qǐng)。
打破循環(huán)等待條件:實(shí)現(xiàn)資源有序分配策略,對(duì)所有設(shè)備實(shí)現(xiàn)分類編號(hào),所有進(jìn)程只能采用按序號(hào)遞增的形式申請(qǐng)資源。
2.類加載過(guò)程

3.synchronized底層實(shí)現(xiàn)原理
https://blog.csdn.net/javazejian/article/details/72828483
4.synchronized與Lock的區(qū)別
1.首先synchronized是java內(nèi)置關(guān)鍵字,在jvm層面,Lock是個(gè)java類;
2.synchronized無(wú)法判斷是否獲取鎖的狀態(tài),Lock可以判斷是否獲取到鎖;
3.synchronized會(huì)自動(dòng)釋放鎖(a 線程執(zhí)行完同步代碼會(huì)釋放鎖 ;b 線程執(zhí)行過(guò)程中發(fā)生異常會(huì)釋放鎖),Lock需在finally中手工釋放鎖(unlock()方法釋放鎖),否則容易造成線程死鎖;
4.用synchronized關(guān)鍵字的兩個(gè)線程1和線程2,如果當(dāng)前線程1獲得鎖,線程2線程等待。如果線程1阻塞,線程2則會(huì)一直等待下去,而Lock鎖就不一定會(huì)等待下去,如果嘗試獲取不到鎖,線程可以不用一直等待就結(jié)束了;
5.synchronized的鎖可重入、不可中斷、非公平,而Lock鎖可重入、可判斷、可公平(兩者皆可)
6.Lock鎖適合大量同步的代碼的同步問(wèn)題,synchronized鎖適合代碼少量的同步問(wèn)題。
5.反射
- JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法,對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性,這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為java語(yǔ)言的反射機(jī)制
- 1.獲取反射中的class對(duì)象
1).使用Class.forName靜態(tài)方法,知道類的全路徑名
Class c1 = Class.forName(“java.lang.String”);
2).直接通過(guò) 類名.class 的方式得到,該方法最為安全可靠,程序性能更高
Class c2 = String.class;
3).通過(guò)對(duì)象調(diào)用 getClass() 方法來(lái)獲取,通常應(yīng)用于不知道具體是什么類
String str = new String("Hello");
Class c3 = str.getClass();
- 2.通過(guò)反射創(chuàng)建類對(duì)象
1).通過(guò) Class 對(duì)象的 newInstance() 方法。
Class clz = Phone.class;
Phone phone = (Phone)clz.newInstance();
2).通過(guò) Constructor 對(duì)象的 newInstance() 方法
Constructor constructor = clz.getConstructor();
Phone phone= (Phone)constructor.newInstance();
通過(guò) Constructor 對(duì)象創(chuàng)建類對(duì)象可以選擇特定構(gòu)造方法,而通過(guò) Class 對(duì)象則只能使用默認(rèn)的無(wú)參數(shù)構(gòu)造方法
Class clz = Phone.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Phone phone = (Phone) constructor.newInstance("華為",6666);
- 3.通過(guò)反射獲取類屬性、方法、構(gòu)造器
getName():獲得類的完整名字。
getFields():獲得類的public類型的屬性。
getDeclaredFields():獲得類的所有屬性。包括private 聲明的和繼承類
getMethods():獲得類的public類型的方法。
getDeclaredMethods():獲得類的所有方法。包括private 聲明的和繼承類
getMethod(String name, Class[] parameterTypes):獲得類的特定方法,name參數(shù)指定方法的名字,parameterTypes 參數(shù)指定方法的參數(shù)類型。
getConstructors():獲得類的public類型的構(gòu)造方法。
getConstructor(Class[] parameterTypes):獲得類的特定構(gòu)造方法,parameterTypes 參數(shù)指定構(gòu)造方法的參數(shù)類型。
6.java序列化
序列化:將 Java 對(duì)象轉(zhuǎn)換成字節(jié)流的過(guò)程。
反序列化:將字節(jié)流轉(zhuǎn)換成 Java 對(duì)象的過(guò)程。
當(dāng) Java 對(duì)象需要在網(wǎng)絡(luò)上傳輸 或者 持久化存儲(chǔ)到文件中時(shí),就需要對(duì) Java 對(duì)象進(jìn)行序列化處理。
序列化的實(shí)現(xiàn):類實(shí)現(xiàn) Serializable 接口,這個(gè)接口沒(méi)有需要實(shí)現(xiàn)的方法。實(shí)現(xiàn) Serializable 接口是為了告訴 jvm 這個(gè)類的對(duì)象可以被序列化。
注意事項(xiàng):
某個(gè)類可以被序列化,則其子類也可以被序列化
聲明為 static 和 transient 的成員變量,不能被序列化。static 成員變量是描述類級(jí)別的屬性,transient 表示臨時(shí)數(shù)據(jù)
反序列化讀取序列化對(duì)象的順序要保持一致
7.動(dòng)態(tài)代理
- 代理模式:代理模式給一個(gè)對(duì)象提供一個(gè)代理對(duì)象,并由代理對(duì)象控制對(duì)原對(duì)象的引用
- 動(dòng)態(tài)代理:方便運(yùn)行時(shí)動(dòng)態(tài)構(gòu)建代理、動(dòng)態(tài)處理代理方法調(diào)用的機(jī)制。實(shí)現(xiàn)方法的增強(qiáng),讓你可以在不修改源碼的情況下,增強(qiáng)一些方法,在方法執(zhí)行前后做任何你想做的事情,甚至根本不去執(zhí)行這個(gè)方法,因?yàn)樵贗nvocationHandler的invoke方法中,可以直接獲取政治調(diào)用方法對(duì)應(yīng)的Method對(duì)象,具體應(yīng)用的話,可以添加調(diào)用日志,做事務(wù)控制等。例如商戶---->明星經(jīng)紀(jì)人(代理)---->明星
java動(dòng)態(tài)代理
- Java的動(dòng)態(tài)代理是基于java.lang.reflect.Proxy、java.lang.reflect.invocationHandler兩個(gè)類來(lái)完成的,使用了反射機(jī)制,基于接口。
- 動(dòng)態(tài)代理和靜態(tài)代理的區(qū)別在于靜態(tài)代理我們需要手動(dòng)的去實(shí)現(xiàn)目標(biāo)對(duì)象的代理類(編譯時(shí)確定被代理的類時(shí)哪一個(gè)),而動(dòng)態(tài)代理可以在運(yùn)行期間動(dòng)態(tài)的生成代理類。
- newProxyInstance()
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
newProxyInstance方法用來(lái)返回一個(gè)代理對(duì)象,這個(gè)方法總共有3個(gè)參數(shù):
ClassLoader loader用來(lái)指明生成代理對(duì)象使用哪個(gè)類裝載器;
Class<?>[] interfaces用來(lái)指明生成哪個(gè)對(duì)象的代理對(duì)象,通過(guò)接口指定;
InvocationHandler h用來(lái)指明產(chǎn)生的這個(gè)代理對(duì)象要做什么事情。
所以我們只需要調(diào)用newProxyInstance方法就可以得到某一個(gè)對(duì)象的代理對(duì)象了。
- InvocationHandler中的invoke()方法
public Object invoke(Object proxy,Method method,Object args){
method.invoke();
}
proxy:代理對(duì)象
method:代理對(duì)象調(diào)用的方法
args:方法參數(shù)
cglib動(dòng)態(tài)代理
- 通過(guò)“繼承”可以繼承父類所有的公開(kāi)方法,然后可以重寫(xiě)這些方法,在重寫(xiě)時(shí)對(duì)這些方法增強(qiáng),這就是cglib的思想。根據(jù)里氏代換原則(LSP),父類需要出現(xiàn)的地方,子類可以出現(xiàn),所以cglib實(shí)現(xiàn)的代理也是可以被正常使用的。
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Cglib動(dòng)態(tài)代理,監(jiān)聽(tīng)開(kāi)始!");
Object invoke = method.invoke(代理對(duì)象,參數(shù)數(shù)組);
System.out.println("Cglib動(dòng)態(tài)代理,監(jiān)聽(tīng)結(jié)束!");
return invoke
}
//定義獲取代理對(duì)象方法
public Object getCglibProxy(Object objectTarget){
//為目標(biāo)對(duì)象target賦值
this.target = objectTarget;
Enhancer enhancer = new Enhancer();
//設(shè)置父類,因?yàn)镃glib是針對(duì)指定的類生成一個(gè)子類,所以需要指定父類
enhancer.setSuperclass(objectTarget.getClass());
enhancer.setCallback(this);// 設(shè)置回調(diào)
Object result = enhancer.create();//創(chuàng)建并返回代理對(duì)象
return result;
}
8.克隆
想對(duì)一個(gè)對(duì)象進(jìn)行處理,又想保留原有的數(shù)據(jù)進(jìn)行接下來(lái)的操作,就需要克隆,java語(yǔ)音中克隆針對(duì)的是類的實(shí)例
淺克?。╯hallowclone)和深克?。╠eepclone)
在淺克隆中,如果原型對(duì)象的成員變量是值類型,將復(fù)制一份給克隆對(duì)象;如果原型對(duì)象的成員變量是引用類型,則將引用對(duì)象的地址復(fù)制一份給克隆對(duì)象,也就是說(shuō)原型對(duì)象和克隆對(duì)象的成員變量指向相同的內(nèi)存地址。
簡(jiǎn)單來(lái)說(shuō),在淺克隆中,當(dāng)對(duì)象被復(fù)制時(shí)只復(fù)制它本身和其中包含的值類型的成員變量,而引用類型的成員對(duì)象并沒(méi)有復(fù)制。
1.被復(fù)制的類需要實(shí)現(xiàn)Clonenable接口(不實(shí)現(xiàn)的話在調(diào)用clone方法會(huì)拋出CloneNotSupportedException異常), 該接口為標(biāo)記接口(不含任何方法)
2.覆蓋clone()方法,訪問(wèn)修飾符設(shè)為public。方法中調(diào)用super.clone()方法得到需要的復(fù)制對(duì)象。(native為本地方法)
image.png
深克隆不僅拷貝對(duì)象本身,而且拷貝對(duì)象包含的引用指向的所有對(duì)象。
image.png
- 也可以通過(guò)BeanUtils和PropertyUtils進(jìn)行對(duì)象復(fù)制
- 通過(guò)序列化實(shí)現(xiàn)對(duì)象的復(fù)制
序列化就是將對(duì)象寫(xiě)到流的過(guò)程,寫(xiě)到流中的對(duì)象是原有對(duì)象的一個(gè)拷貝,而原對(duì)象仍然存在于內(nèi)存中。通過(guò)序列化實(shí)現(xiàn)的拷貝不僅可以復(fù)制對(duì)象本身,而且可以復(fù)制其引用的成員對(duì)象,因此通過(guò)序列化將對(duì)象寫(xiě)到一個(gè)流中,再?gòu)牧骼飳⑵渥x出來(lái),可以實(shí)現(xiàn)深克隆。需要注意的是能夠?qū)崿F(xiàn)序列化的對(duì)象其類必須實(shí)現(xiàn)Serializable接口,否則無(wú)法實(shí)現(xiàn)序列化操作。

