1硕并、ReentrantLock和Synchronized的區(qū)別,以及實(shí)現(xiàn)原理
ReentrantLock是java代碼實(shí)現(xiàn)秧荆,Synchronized是字節(jié)碼實(shí)現(xiàn)倔毙,ReentrantLock可使用公平鎖、可根據(jù)Condition分組喚醒線程辰如、而不是像synchronized要么隨機(jī)喚醒一個(gè)線程要么喚醒全部線程普监,ReenTrantLock提供了一種能夠中斷等待鎖的線程的機(jī)制,通過(guò)lock.lockInterruptibly()來(lái)實(shí)現(xiàn)這個(gè)機(jī)制琉兜。
ReentrantLock內(nèi)部實(shí)現(xiàn)原理:AbstractQueuedSynchronizer簡(jiǎn)稱(chēng)AQS凯正,AQS維護(hù)一個(gè)volatile int state字段和雙向隊(duì)列來(lái)實(shí)現(xiàn)。AQS詳解
Synchronized實(shí)現(xiàn)原理:代碼塊時(shí)是在字節(jié)碼中加入moniterenter和moniterexit豌蟋,當(dāng)執(zhí)行到moniterenter時(shí)會(huì)獲取鎖定對(duì)象的鎖廊散,方法時(shí)是在Class文件的方法表中將該方法的access_flags存放ACC_SYNCHRONIZED。鎖定的對(duì)象的加鎖是通過(guò)對(duì)象頭MARKWORD中指向的當(dāng)前對(duì)象的ObjectMoniter來(lái)加鎖梧疲。Synchronized的內(nèi)部實(shí)現(xiàn)原理以及Moniter實(shí)現(xiàn)原理允睹。
2、jvm問(wèn)題排查
1幌氮、程序hung诅允堋:線程死鎖、線程堵塞该互。通過(guò)jps獲取當(dāng)前進(jìn)程id米者,jstack -l pid,出現(xiàn)BLOCKED宇智、deadlock蔓搞。
2、CPU100%: jps查看pid随橘,top -H -p pid查看cpu最高的線程id,jstack pid> a.log 然后在a.log中搜索線程id的16進(jìn)制喂分。
3、頻繁full gc:可能是oom机蔗。jmap -dump:format=b,file=/home/admin/dump.bin pid導(dǎo)出堆的信息蒲祈,用VisualVM進(jìn)行分析甘萧。jstat -gcutil pid查看gc情況。一次線上OOM排查經(jīng)過(guò)
3讳嘱、java 中的鎖 -- 偏向鎖幔嗦、輕量級(jí)鎖酿愧、自旋鎖沥潭、重量級(jí)鎖
偏向鎖適用于單個(gè)線程時(shí)提高性能,輕量級(jí)鎖適用于多個(gè)線程交替執(zhí)行嬉挡。
偏向鎖:首先CAS修改線程id為當(dāng)前線程id钝鸽,失敗并且線程id不是當(dāng)前線程,在安全點(diǎn)判斷持有鎖的線程是否存在庞钢,不存在標(biāo)示為未鎖定拔恰,存在升級(jí)為輕量級(jí)鎖。
輕量級(jí)鎖:復(fù)制MARKWORD到LOCK record里基括,CAS修改線程id為當(dāng)前線程id颜懊,失敗并且線程id不是當(dāng)前線程,進(jìn)入自旋CAS獲取风皿,獲取失敗升級(jí)為重量級(jí)鎖河爹。執(zhí)行結(jié)束,復(fù)制的那份MARK word用CAS替換桐款,如果失敗也進(jìn)入重量級(jí)鎖咸这。java 中的鎖?關(guān)于偏向鎖、輕量級(jí)鎖將的不是很好魔眨,參考這個(gè)《JVM源碼分析之synchronized實(shí)現(xiàn)》
4媳维、堆外內(nèi)存使用以及回收機(jī)制
堆外內(nèi)存時(shí)jvm以外的內(nèi)存,當(dāng)建立一個(gè)堆外內(nèi)存的時(shí)候會(huì)在堆中創(chuàng)建一個(gè)Cleaner對(duì)象對(duì)應(yīng)DirectByteBuffer遏暴,當(dāng)DirectByteBuffer對(duì)象被回收時(shí)侄刽,把cleaner對(duì)象放到ReferenceQueue隊(duì)列,在FULL gc時(shí)會(huì)調(diào)用ReferenceQueue中所有Cleaner對(duì)象的clear方法朋凉。也可以手動(dòng)獲取Cleaner對(duì)象州丹,并調(diào)用clear方法進(jìn)行回收。堆外內(nèi)存的回收機(jī)制分析
ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 200);//200M堆外內(nèi)存
((DirectBuffer)buffer).cleaner().clean();//手動(dòng)回收
5侥啤、強(qiáng)引用当叭、軟引用、弱引用盖灸、虛引用
強(qiáng)引用:只要引用存在永不回收蚁鳖。比如new 一個(gè)對(duì)象。
軟引用:內(nèi)存溢出之前進(jìn)行回收赁炎。SoftReference醉箕。應(yīng)用:緩存
弱引用:第二次垃圾回收時(shí)回收钾腺。WeakReference。
虛引用:垃圾回收時(shí)回收讥裤。PhantomReference放棒。
6、動(dòng)態(tài)代理
jdk動(dòng)態(tài)代理:被代理類(lèi)必須實(shí)現(xiàn)了接口己英。原理實(shí)現(xiàn)InvocationHandler接口间螟,內(nèi)部還是使用的反射。
cglib代理:被代理類(lèi)不時(shí)必須實(shí)現(xiàn)接口损肛,性能比不上jdk厢破,通過(guò)繼承被代理類(lèi)來(lái)實(shí)現(xiàn)。需要實(shí)現(xiàn)MethodInterceptor接口治拿。
7摩泪、ArrayList、Vector劫谅、HashSet见坑、HashTable默認(rèn)容量和擴(kuò)容
ArrayList:默認(rèn)容量:10 擴(kuò)容增量:1.5*原數(shù)組長(zhǎng)度
Vector:默認(rèn)容量:10?擴(kuò)容增量:2*原數(shù)組長(zhǎng)度
HashSet:默認(rèn)容量:16?擴(kuò)容增量:2*原數(shù)組長(zhǎng)度
HashTable:默認(rèn)11?擴(kuò)容增量:2*原數(shù)組長(zhǎng)度+1
8、淺拷貝和深拷貝的區(qū)別
淺拷貝:只拷貝當(dāng)前對(duì)象捏检,而當(dāng)前對(duì)象引用的其它對(duì)象還是引用同一個(gè)對(duì)象荞驴。
深拷貝:不僅拷貝當(dāng)前對(duì)象還拷貝當(dāng)前對(duì)象引用的對(duì)象。
A a = new A();A b =a;//只是引用 不叫拷貝
9未檩、線程的五種狀態(tài)和線程池的五種狀態(tài)以及狀態(tài)流轉(zhuǎn)
線程五種狀態(tài):新建New戴尸、就緒Runnable、運(yùn)行Running冤狡、阻塞Blocked及死亡Dead孙蒙。
線程池的5種狀態(tài):Running、ShutDown悲雳、Stop挎峦、Tidying、Terminated合瓢。