什么情況下會(huì)發(fā)生死鎖
出現(xiàn)死鎖,有這四個(gè)必要條件:互斥條件、請(qǐng)求和保持、不可剝奪、循環(huán)等待
- 互斥條件: 一個(gè)資源每次只能被一個(gè)進(jìn)程使用,即在一段時(shí)間內(nèi)某 資源僅為一個(gè)進(jìn)程所占有。此時(shí)若有其他進(jìn)程請(qǐng)求該資源,則請(qǐng)求進(jìn)程只能等待。
- 請(qǐng)求與保持條件: 進(jìn)程已經(jīng)保持了至少一個(gè)資源,但又提出了新的資源請(qǐng)求,而該資源 已被其他進(jìn)程占有,此時(shí)請(qǐng)求進(jìn)程被阻塞,但對(duì)自己已獲得的資源保持不放。
- 不可剝奪條件: 進(jìn)程所獲得的資源在未使用完畢之前,不能被其他進(jìn)程強(qiáng)行奪走,即只能 由獲得該資源的進(jìn)程自己來(lái)釋放(只能是主動(dòng)釋放)。
- 循環(huán)等待條件: 若干進(jìn)程間形成首尾相接循環(huán)等待資源的關(guān)系
只要系統(tǒng)發(fā)生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會(huì)發(fā)生死鎖
java模擬死鎖
public class DeadLockTest{
public static void main(String[] args) {
Thread t1 = new Thread(new DeadLock(1));
Thread t2 = new Thread(new DeadLock(2));
t1.start();
t2.start();
}
}
class DeadLock implements Runnable{
private int flag;
private static Object o1 = new Object();
private static Object o2 = new Object();
DeadLock(int _flag){
this.flag = _flag;
}
@Override
public void run() {
System.out.println("flag: " + flag);
if(flag == 1){
synchronized(o1){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o2){
System.out.println("1");
}
}
}
else if(flag == 2){
synchronized(o2){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(o1){
System.out.println("2");
}
}
}
}
}
JVM gc算法
哪些對(duì)象該被GC? 如果一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈,該對(duì)象就是不可達(dá)對(duì)象,即可以被GC。
一、標(biāo)記清除算法(Mark-and-Sweep)
標(biāo)記清除算法是最基礎(chǔ)的收集算法,后面的算法都是基于該算法擴(kuò)展的,分為兩個(gè)階段:
標(biāo)記階段(Mark phase):
從GC Roots出發(fā),沿著引用鏈,遇到對(duì)象就標(biāo)記該對(duì)象,直到所有可達(dá)對(duì)象都被標(biāo)記。
清除階段(Sweep phase):
掃描整個(gè)heap,回收那些在標(biāo)記階段未被標(biāo)記的對(duì)象的內(nèi)存
二、停止復(fù)制算法(Stop-and-Copy)
停止復(fù)制算法將可用內(nèi)存分為等量的兩塊,每次只使用其中的一塊,當(dāng)這一塊無(wú)法滿足新的內(nèi)存分配時(shí),即需要GC時(shí),就掃描該塊,將還存活的對(duì)象復(fù)制到另一塊上面,然后再把已使用過(guò)的內(nèi)存空間一次清理掉。
三、標(biāo)記整理(壓縮)算法(Mark-and-Compact)
標(biāo)記整理算法和標(biāo)記清理算法類似,也分為兩個(gè)階段:
標(biāo)記階段(Mark):從GC Roots出發(fā),沿著引用鏈,遇到對(duì)象就標(biāo)記該對(duì)象,直到所有可達(dá)對(duì)象都被標(biāo)記。
整理(壓縮)階段(Compact):把所有的存活對(duì)象往一端移,然后清理掉端邊界外的內(nèi)存。
注意:無(wú)論是哪種算法哪種收集器,在枚舉根節(jié)點(diǎn)時(shí)都是要停頓(停頓指得是暫停所有用戶線程),只是根據(jù)算法的不同以及收集器的不同該停頓時(shí)間的長(zhǎng)短不同而已。
MySQL存儲(chǔ)引擎有哪幾種,各有什么特點(diǎn)
TODO
redis如何從左向右刪除list元素
TODO
Spring MVC 一個(gè)請(qǐng)求處理流程
Spring工作流程描述
- 用戶向服務(wù)器發(fā)送請(qǐng)求,請(qǐng)求被Spring 前端控制Servelt DispatcherServlet捕獲;
- DispatcherServlet對(duì)請(qǐng)求URL進(jìn)行解析,得到請(qǐng)求資源標(biāo)識(shí)符(URI)。然后根據(jù)該URI,調(diào)用HandlerMapping獲得該Handler配置的所有相關(guān)的對(duì)象(包括Handler對(duì)象以及Handler對(duì)象對(duì)應(yīng)的攔截器),最后以HandlerExecutionChain對(duì)象的形式返回;
- DispatcherServlet 根據(jù)獲得的Handler,選擇一個(gè)合適的HandlerAdapter。(附注:如果成功獲得HandlerAdapter后,此時(shí)將開(kāi)始執(zhí)行攔截器的preHandler(...)方法)
- 提取Request中的模型數(shù)據(jù),填充Handler入?yún)ⅲ_(kāi)始執(zhí)行Handler(Controller)。 在填充Handler的入?yún)⑦^(guò)程中,根據(jù)你的配置,Spring將幫你做一些額外的工作:
HttpMessageConveter: 將請(qǐng)求消息(如Json、xml等數(shù)據(jù))轉(zhuǎn)換成一個(gè)對(duì)象,將對(duì)象轉(zhuǎn)換為指定的響應(yīng)信息
數(shù)據(jù)轉(zhuǎn)換:對(duì)請(qǐng)求消息進(jìn)行數(shù)據(jù)轉(zhuǎn)換。如String轉(zhuǎn)換成Integer、Double等
數(shù)據(jù)根式化:對(duì)請(qǐng)求消息進(jìn)行數(shù)據(jù)格式化。 如將字符串轉(zhuǎn)換成格式化數(shù)字或格式化日期等
數(shù)據(jù)驗(yàn)證: 驗(yàn)證數(shù)據(jù)的有效性(長(zhǎng)度、格式等),驗(yàn)證結(jié)果存儲(chǔ)到BindingResult或Error中- Handler執(zhí)行完成后,向DispatcherServlet 返回一個(gè)ModelAndView對(duì)象;
- 根據(jù)返回的ModelAndView,選擇一個(gè)適合的ViewResolver(必須是已經(jīng)注冊(cè)到Spring容器中的ViewResolver)返回給DispatcherServlet ;
- ViewResolver 結(jié)合Model和View,來(lái)渲染視圖
- 將渲染結(jié)果返回給客戶端。
向zookeeper集群寫(xiě)數(shù)據(jù),內(nèi)部流程
TODO