1.死鎖
死鎖是指兩個或兩個以上的線程在執(zhí)行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象扣泊,若無外力作用,它們都將無法推進(jìn)下去。此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖雳灵,這些永遠(yuǎn)在互相等待的進(jìn)程稱為死鎖進(jìn)程
-
條件:
1.互斥條件:進(jìn)程對于所分配到的資源具有排它性,即一個資源只能被一個進(jìn)程占用仅淑,直到被該進(jìn)程釋放
2.請求和保持條件:一個進(jìn)程因請求被占用資源而發(fā)生阻塞時晕拆,對已獲得的資源保持不放。
3.不剝奪條件:任何一個資源在沒被該進(jìn)程釋放之前嘀掸,任何其他進(jìn)程都無法對他剝奪占用
4.循環(huán)等待條件:當(dāng)發(fā)生死鎖時紫岩,所等待的進(jìn)程必定會形成一個環(huán)路(類似于死循環(huán)),造成永久阻塞睬塌。 -
避免
死鎖避免的基本思想:系統(tǒng)對進(jìn)程發(fā)出每一個系統(tǒng)能夠滿足的資源申請進(jìn)行動態(tài)檢查泉蝌,并根據(jù)檢查結(jié)果決定是否分配資源,如果分配后系統(tǒng)可能發(fā)生死鎖,則不予分配揩晴,否則予以分配勋陪。這是一種保證系統(tǒng)不進(jìn)入死鎖狀態(tài)的動態(tài)策略打破互斥條件:改造獨占性資源為虛擬資源,大部分資源已無法改造文狱。
打破不可搶占條件:當(dāng)一進(jìn)程占有一獨占性資源后又申請一獨占性資源而無法滿足粥鞋,則退出原占有的資源。
打破占有且申請條件:采用資源預(yù)先分配策略瞄崇,即進(jìn)程運行前申請全部資源呻粹,滿足則運行,不然就等待苏研,這樣就不會占有且申請等浊。
打破循環(huán)等待條件:實現(xiàn)資源有序分配策略,對所有設(shè)備實現(xiàn)分類編號摹蘑,所有進(jìn)程只能采用按序號遞增的形式申請資源筹燕。
2.類加載過程
3.synchronized底層實現(xiàn)原理
https://blog.csdn.net/javazejian/article/details/72828483
4.synchronized與Lock的區(qū)別
1.首先synchronized是java內(nèi)置關(guān)鍵字,在jvm層面,Lock是個java類撒踪;
2.synchronized無法判斷是否獲取鎖的狀態(tài)过咬,Lock可以判斷是否獲取到鎖;
3.synchronized會自動釋放鎖(a 線程執(zhí)行完同步代碼會釋放鎖 制妄;b 線程執(zhí)行過程中發(fā)生異常會釋放鎖)掸绞,Lock需在finally中手工釋放鎖(unlock()方法釋放鎖),否則容易造成線程死鎖耕捞;
4.用synchronized關(guān)鍵字的兩個線程1和線程2衔掸,如果當(dāng)前線程1獲得鎖,線程2線程等待俺抽。如果線程1阻塞敞映,線程2則會一直等待下去,而Lock鎖就不一定會等待下去磷斧,如果嘗試獲取不到鎖振愿,線程可以不用一直等待就結(jié)束了;
5.synchronized的鎖可重入瞳抓、不可中斷埃疫、非公平,而Lock鎖可重入孩哑、可判斷栓霜、可公平(兩者皆可)
6.Lock鎖適合大量同步的代碼的同步問題,synchronized鎖適合代碼少量的同步問題横蜒。
5.反射
- JAVA反射機制是在運行狀態(tài)中胳蛮,對于任意一個類,都能夠知道這個類的所有屬性和方法丛晌,對于任意一個對象仅炊,都能夠調(diào)用它的任意一個方法和屬性,這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機制
- 1.獲取反射中的class對象
1).使用Class.forName靜態(tài)方法澎蛛,知道類的全路徑名
Class c1 = Class.forName(“java.lang.String”);
2).直接通過 類名.class 的方式得到抚垄,該方法最為安全可靠,程序性能更高
Class c2 = String.class;
3).通過對象調(diào)用 getClass() 方法來獲取,通常應(yīng)用于不知道具體是什么類
String str = new String("Hello");
Class c3 = str.getClass();
- 2.通過反射創(chuàng)建類對象
1).通過 Class 對象的 newInstance() 方法谋逻。
Class clz = Phone.class;
Phone phone = (Phone)clz.newInstance();
2).通過 Constructor 對象的 newInstance() 方法
Constructor constructor = clz.getConstructor();
Phone phone= (Phone)constructor.newInstance();
通過 Constructor 對象創(chuàng)建類對象可以選擇特定構(gòu)造方法呆馁,而通過 Class 對象則只能使用默認(rèn)的無參數(shù)構(gòu)造方法
Class clz = Phone.class;
Constructor constructor = clz.getConstructor(String.class, int.class);
Phone phone = (Phone) constructor.newInstance("華為",6666);
- 3.通過反射獲取類屬性、方法毁兆、構(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 對象轉(zhuǎn)換成字節(jié)流的過程。
反序列化:將字節(jié)流轉(zhuǎn)換成 Java 對象的過程煮寡。
當(dāng) Java 對象需要在網(wǎng)絡(luò)上傳輸 或者 持久化存儲到文件中時,就需要對 Java 對象進(jìn)行序列化處理犀呼。
序列化的實現(xiàn):類實現(xiàn) Serializable 接口幸撕,這個接口沒有需要實現(xiàn)的方法。實現(xiàn) Serializable 接口是為了告訴 jvm 這個類的對象可以被序列化外臂。
注意事項:
某個類可以被序列化坐儿,則其子類也可以被序列化
聲明為 static 和 transient 的成員變量,不能被序列化宋光。static 成員變量是描述類級別的屬性貌矿,transient 表示臨時數(shù)據(jù)
反序列化讀取序列化對象的順序要保持一致
7.動態(tài)代理
- 代理模式:代理模式給一個對象提供一個代理對象,并由代理對象控制對原對象的引用
- 動態(tài)代理:方便運行時動態(tài)構(gòu)建代理罪佳、動態(tài)處理代理方法調(diào)用的機制逛漫。實現(xiàn)方法的增強,讓你可以在不修改源碼的情況下赘艳,增強一些方法酌毡,在方法執(zhí)行前后做任何你想做的事情,甚至根本不去執(zhí)行這個方法蕾管,因為在InvocationHandler的invoke方法中枷踏,可以直接獲取政治調(diào)用方法對應(yīng)的Method對象,具體應(yīng)用的話掰曾,可以添加調(diào)用日志旭蠕,做事務(wù)控制等。例如商戶---->明星經(jīng)紀(jì)人(代理)---->明星
java動態(tài)代理
- Java的動態(tài)代理是基于java.lang.reflect.Proxy旷坦、java.lang.reflect.invocationHandler兩個類來完成的掏熬,使用了反射機制,基于接口塞蹭。
- 動態(tài)代理和靜態(tài)代理的區(qū)別在于靜態(tài)代理我們需要手動的去實現(xiàn)目標(biāo)對象的代理類(編譯時確定被代理的類時哪一個)孽江,而動態(tài)代理可以在運行期間動態(tài)的生成代理類。
- newProxyInstance()
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
newProxyInstance方法用來返回一個代理對象番电,這個方法總共有3個參數(shù):
ClassLoader loader用來指明生成代理對象使用哪個類裝載器岗屏;
Class<?>[] interfaces用來指明生成哪個對象的代理對象辆琅,通過接口指定;
InvocationHandler h用來指明產(chǎn)生的這個代理對象要做什么事情这刷。
所以我們只需要調(diào)用newProxyInstance方法就可以得到某一個對象的代理對象了婉烟。
- InvocationHandler中的invoke()方法
public Object invoke(Object proxy,Method method,Object args){
method.invoke();
}
proxy:代理對象
method:代理對象調(diào)用的方法
args:方法參數(shù)
cglib動態(tài)代理
- 通過“繼承”可以繼承父類所有的公開方法,然后可以重寫這些方法暇屋,在重寫時對這些方法增強似袁,這就是cglib的思想。根據(jù)里氏代換原則(LSP)咐刨,父類需要出現(xiàn)的地方昙衅,子類可以出現(xiàn),所以cglib實現(xiàn)的代理也是可以被正常使用的定鸟。
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Cglib動態(tài)代理而涉,監(jiān)聽開始!");
Object invoke = method.invoke(代理對象联予,參數(shù)數(shù)組);
System.out.println("Cglib動態(tài)代理啼县,監(jiān)聽結(jié)束!");
return invoke
}
//定義獲取代理對象方法
public Object getCglibProxy(Object objectTarget){
//為目標(biāo)對象target賦值
this.target = objectTarget;
Enhancer enhancer = new Enhancer();
//設(shè)置父類,因為Cglib是針對指定的類生成一個子類沸久,所以需要指定父類
enhancer.setSuperclass(objectTarget.getClass());
enhancer.setCallback(this);// 設(shè)置回調(diào)
Object result = enhancer.create();//創(chuàng)建并返回代理對象
return result;
}
8.克隆
想對一個對象進(jìn)行處理季眷,又想保留原有的數(shù)據(jù)進(jìn)行接下來的操作,就需要克隆卷胯,java語音中克隆針對的是類的實例
淺克伦庸巍(shallowclone)和深克隆(deepclone)
在淺克隆中窑睁,如果原型對象的成員變量是值類型话告,將復(fù)制一份給克隆對象;如果原型對象的成員變量是引用類型卵慰,則將引用對象的地址復(fù)制一份給克隆對象沙郭,也就是說原型對象和克隆對象的成員變量指向相同的內(nèi)存地址。
簡單來說裳朋,在淺克隆中病线,當(dāng)對象被復(fù)制時只復(fù)制它本身和其中包含的值類型的成員變量,而引用類型的成員對象并沒有復(fù)制鲤嫡。
1.被復(fù)制的類需要實現(xiàn)Clonenable接口(不實現(xiàn)的話在調(diào)用clone方法會拋出CloneNotSupportedException異常)送挑, 該接口為標(biāo)記接口(不含任何方法)
2.覆蓋clone()方法,訪問修飾符設(shè)為public暖眼。方法中調(diào)用super.clone()方法得到需要的復(fù)制對象惕耕。(native為本地方法)
image.png
深克隆不僅拷貝對象本身,而且拷貝對象包含的引用指向的所有對象诫肠。
image.png
- 也可以通過BeanUtils和PropertyUtils進(jìn)行對象復(fù)制
- 通過序列化實現(xiàn)對象的復(fù)制
序列化就是將對象寫到流的過程司澎,寫到流中的對象是原有對象的一個拷貝欺缘,而原對象仍然存在于內(nèi)存中。通過序列化實現(xiàn)的拷貝不僅可以復(fù)制對象本身挤安,而且可以復(fù)制其引用的成員對象谚殊,因此通過序列化將對象寫到一個流中,再從流里將其讀出來蛤铜,可以實現(xiàn)深克隆嫩絮。需要注意的是能夠?qū)崿F(xiàn)序列化的對象其類必須實現(xiàn)Serializable接口,否則無法實現(xiàn)序列化操作围肥。