在網(wǎng)上看到一篇專(zhuān)門(mén)匯總面試題的文章赶撰,于是一時(shí)興起,就把其內(nèi)容整理了一番炕舵,因?yàn)樵膯?wèn)題和答案不完整,且混在一起跟畅,于是有了這篇Java問(wèn)題總結(jié)
一幕侠、Java基礎(chǔ)
-
為什么java可以一次編譯,到處運(yùn)行碍彭?
- 答:一處編譯到處運(yùn)行晤硕,主要依賴(lài)于不同平臺(tái)上統(tǒng)一的JVM運(yùn)行程序;我們知道不同的平臺(tái)擁有者不同的架構(gòu)庇忌,不同的執(zhí)行標(biāo)準(zhǔn)等舞箍,使得不管什么情況下,要使得一套代碼在不同的操作系統(tǒng)上運(yùn)行遇上了阻礙皆疹。然而Sun公司的工程師們給不同的平臺(tái)都開(kāi)發(fā)了一個(gè)模擬軟件疏橄,這個(gè)軟件是用來(lái)運(yùn)行Java程序的,這就是JVM略就,JVM并不跨平臺(tái)捎迫,但是使得在JVM上運(yùn)行的Java程序變得通用;即JVM接收的程序是跨平臺(tái)的表牢,本身不跨平臺(tái)窄绒,把接收的Java程序經(jīng)過(guò)處理,調(diào)用宿主機(jī)的硬件完成運(yùn)算崔兴;
-
StringBuffer和StringBuilder區(qū)別彰导?
- 答:StringBuffer和StringBuilder都是可變字符串蛔翅,即可改變?cè)凶址膬?nèi)容,但是區(qū)別在于:StringBuffer是線程安全的位谋,其中的方法都添加了Synchronized關(guān)鍵字山析,所以其執(zhí)行的效率相對(duì)較低;而StringBuilder相對(duì)于StringBuffer少了Synchronized關(guān)鍵字掏父,所以是線程不安全的笋轨,故其執(zhí)行的效率相對(duì)較高;
-
String為什么是不可變的赊淑?
- 答:因?yàn)榉庋bString的本質(zhì)是一個(gè)使用private final修飾的字符數(shù)組翩腐,所以正常情況下,這個(gè)字符數(shù)組是不可變的膏燃,但是我們可以使用反射的方式對(duì)元字符串進(jìn)行修改茂卦,代碼如下,不過(guò)一般情況下不會(huì)這么使用组哩;
public static void testReflection() throws Exception { String s = "Hello World"; System.out.println("s = " + s); Field valueField = String.class.getDeclaredField("value"); valueField.setAccessible(true); char[] value = (char[]) valueField.get(s); value[5] = '_'; System.out.println("s = " + s); }
- 答:因?yàn)榉庋bString的本質(zhì)是一個(gè)使用private final修飾的字符數(shù)組翩腐,所以正常情況下,這個(gè)字符數(shù)組是不可變的膏燃,但是我們可以使用反射的方式對(duì)元字符串進(jìn)行修改茂卦,代碼如下,不過(guò)一般情況下不會(huì)這么使用组哩;
-
StringBuilder線程不安全體現(xiàn)在哪等龙?
- 答:在多線程環(huán)境下,StringBuilder對(duì)象常常會(huì)使得多個(gè)線程同時(shí)操作伶贰,造成一個(gè)結(jié)果覆蓋另一個(gè)結(jié)果的情況蛛砰,從而造成最后結(jié)果錯(cuò)誤!
-
ArrayList和LinkedList區(qū)別黍衙?
- 答:①數(shù)據(jù)結(jié)構(gòu)的區(qū)別:ArrayList是基于數(shù)組的數(shù)據(jù)結(jié)構(gòu)泥畅,而LinkedList是基于鏈表的數(shù)據(jù)結(jié)構(gòu);②性能的區(qū)別:查詢和更新數(shù)據(jù)方面:ArrayList優(yōu)于LinkedList琅翻,因?yàn)锳rrayList可以根據(jù)對(duì)象的地址和索引直接計(jì)算出要查找或者要更新的對(duì)象的地址位仁,而LinkedList需要遍歷所有的節(jié)點(diǎn),相比之下肯定速度上有影響方椎;新增和刪除數(shù)據(jù)方面聂抢,這兩個(gè)數(shù)據(jù)結(jié)構(gòu)不一定,因?yàn)閷?duì)于ArrayList而言會(huì)新增可能觸發(fā)擴(kuò)容的問(wèn)題和利用System.arraycopy方法進(jìn)行數(shù)據(jù)的復(fù)制移位棠众,對(duì)于LinkedList需要遍歷查找節(jié)點(diǎn)琳疏,找到后進(jìn)行節(jié)點(diǎn)的銜接或者移除;
-
ArrayList有初始容量嗎闸拿?容量不夠怎么辦 空盼,擴(kuò)容為多大?
- ArrayList空參構(gòu)造過(guò)程:
- 初始情況:elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}新荤; size = 0;
- 當(dāng)向數(shù)組中添加第一個(gè)元素時(shí)揽趾,通過(guò)add(E e)方法中調(diào)用的ensureCapacityInternal(size + 1)方法,即ensureCapacityInternal(1)迟隅;
- 在ensureCapacityInternal(int minCapacity)方法中但骨,可得的minCapacity=DEFAULT_CAPACITY=10,然后再調(diào)用ensureExplicitCapacity(minCapacity)方法智袭,即ensureExplicitCapacity(10)奔缠;
- 在ensureExplicitCapacity(minCapacity)方法中調(diào)用grow(minCapacity)方法,即grow(10)吼野,此處為真正具體的數(shù)組擴(kuò)容的算法校哎,在此方法中,通過(guò)elementData = Arrays.copyOf(elementData, 10)具體實(shí)現(xiàn)了elementData數(shù)組初始容量為10的構(gòu)造瞳步。
- 在JDK1.7和1.8中闷哆,如果通過(guò)無(wú)參構(gòu)造的話,初始數(shù)組容量為0单起,當(dāng)真正對(duì)數(shù)組進(jìn)行添加時(shí)抱怔,才真正分配容量。每次按照1.5倍(位運(yùn)算)的比率通過(guò)copeOf的方式擴(kuò)容嘀倒。在JDK1.6中屈留,如果通過(guò)無(wú)參構(gòu)造的話,初始數(shù)組容量為10.每次通過(guò)copeOf的方式擴(kuò)容后容量為原來(lái)的1.5倍加1测蘑;
- ArrayList空參構(gòu)造過(guò)程:
-
如果Arraylist當(dāng)前容量是10灌危,且有9個(gè)數(shù)據(jù),那么是添加第10個(gè)數(shù)據(jù)時(shí)擴(kuò)容還是第11個(gè)碳胳?擴(kuò)容怎么實(shí)現(xiàn)的勇蝙,為什么采用復(fù)制數(shù)組的方式而不是往后直接添加數(shù)據(jù)?
- 在現(xiàn)在常用的JDK8中挨约,擴(kuò)容是在添加第11個(gè)元素的時(shí)候才會(huì)觸發(fā)的味混;擴(kuò)容步驟:①調(diào)用ArrayList的add方法;②add方法中第一行就調(diào)用了容量檢查的方法ensureCapacityInternal诫惭,參數(shù)是要添加一個(gè)元素惜傲,這個(gè)數(shù)組的最小容量大小(即:已添加的元素個(gè)數(shù)+1);③這個(gè)方法內(nèi)部先調(diào)用方法calculateCapacity確定最小容量贝攒,其實(shí)就是如果存儲(chǔ)元素的數(shù)組是空的盗誊,就獲取默認(rèn)容量大小和傳遞進(jìn)來(lái)的最小容量取其大者為確定的容量最小值,否則返回傳遞進(jìn)來(lái)的最小容量值隘弊;④然后把結(jié)果進(jìn)一步傳遞到ensureExplicitCapacity中來(lái)確定是否擴(kuò)容哈踱,機(jī)制:如果傳遞進(jìn)來(lái)的容量最小值大于目前數(shù)組的容量,就會(huì)調(diào)用grow方法進(jìn)行擴(kuò)容梨熙,并傳遞參數(shù)最小容量开镣,否則不會(huì)調(diào)用grow方法;⑤擴(kuò)容的機(jī)制:
int newCapacity = oldCapacity + (oldCapacity >> 1);
咽扇,即每一次讓梁都是擴(kuò)展到之前容量的1.5倍邪财;當(dāng)然下面還進(jìn)行了一些校驗(yàn)陕壹,這里就不說(shuō)了;
- 在現(xiàn)在常用的JDK8中挨约,擴(kuò)容是在添加第11個(gè)元素的時(shí)候才會(huì)觸發(fā)的味混;擴(kuò)容步驟:①調(diào)用ArrayList的add方法;②add方法中第一行就調(diào)用了容量檢查的方法ensureCapacityInternal诫惭,參數(shù)是要添加一個(gè)元素惜傲,這個(gè)數(shù)組的最小容量大小(即:已添加的元素個(gè)數(shù)+1);③這個(gè)方法內(nèi)部先調(diào)用方法calculateCapacity確定最小容量贝攒,其實(shí)就是如果存儲(chǔ)元素的數(shù)組是空的盗誊,就獲取默認(rèn)容量大小和傳遞進(jìn)來(lái)的最小容量取其大者為確定的容量最小值,否則返回傳遞進(jìn)來(lái)的最小容量值隘弊;④然后把結(jié)果進(jìn)一步傳遞到ensureExplicitCapacity中來(lái)確定是否擴(kuò)容哈踱,機(jī)制:如果傳遞進(jìn)來(lái)的容量最小值大于目前數(shù)組的容量,就會(huì)調(diào)用grow方法進(jìn)行擴(kuò)容梨熙,并傳遞參數(shù)最小容量开镣,否則不會(huì)調(diào)用grow方法;⑤擴(kuò)容的機(jī)制:
- 詳述TreeMap树埠,TreeSet糠馆,HashSet,HashMap怎憋,HashTable又碌,ConcurrentHashMap的實(shí)現(xiàn)原理;
- HashMap:數(shù)組+鏈表/紅黑樹(shù)绊袋,數(shù)組長(zhǎng)度少于MIN_TREEIFY_CAPACITY是不優(yōu)先轉(zhuǎn)紅黑樹(shù)的毕匀,而是優(yōu)先進(jìn)行擴(kuò)容;
- 說(shuō)下hashmap put的過(guò)程癌别;
- key的hashcode高16位與低16位異或運(yùn)算得到新的hash皂岔,為了讓數(shù)據(jù)(特別是在當(dāng)前容量不大的情況下)散列更均勻,然后把異或計(jì)算出的新hash與此時(shí)的hashmap容量-1做&運(yùn)算展姐,得到插入下標(biāo)凤薛。為什么要做&運(yùn)算呢?因?yàn)槎M(jìn)制運(yùn)算速度快诞仓,還可以取模缤苫。之后如果下標(biāo)位數(shù)組無(wú)數(shù)據(jù)則直接插入,如果有數(shù)據(jù)則鏈表往下逐個(gè)進(jìn)行hash比較墅拭,如果產(chǎn)生hash碰撞再進(jìn)行==或者equals比較key是否一樣活玲,一樣則覆蓋原數(shù)據(jù),否則添加到鏈表后面谍婉。
- 說(shuō)說(shuō)你對(duì)hash的理解舒憾。HashSet是怎么去重的?
- 發(fā)生hash沖突怎么辦穗熬?
- JDK1.7和JDK1.8的HashMap有什么區(qū)別镀迂?
- 抽象類(lèi)接口區(qū)別有哪些?接口中可以定義靜態(tài)公共方法嗎唤蔗?接口種可以定義方法的實(shí)現(xiàn)嗎探遵?
- 為什么重寫(xiě)equals方法最好也得重寫(xiě)hashcode?
- 序列化作用有哪些?
- 定時(shí)器的實(shí)現(xiàn)方式有哪些妓柜?
- Integer緩存是什么箱季?有什么作用?
- Comparable接口和Comparator接口實(shí)現(xiàn)比較的區(qū)別和用法棍掐,Arrays靜態(tài)類(lèi)如何實(shí)現(xiàn)排序的藏雏?
- http和https區(qū)別(https用了什么證書(shū),怎樣在網(wǎng)絡(luò)傳輸中實(shí)現(xiàn)作煌,我當(dāng)時(shí)回答了osi七層掘殴,TCP udp 赚瘦,三次握手,四次斷開(kāi))
- 在Java中>>奏寨、>>>的區(qū)別
- >>代表算術(shù)移位也就是用符號(hào)位填充最高位起意。
- >>代表邏輯移位即用0填充最高位。
- 對(duì)于正整數(shù)兩者基本相似
- 對(duì)于負(fù)數(shù)服爷,算術(shù)移位后扔是負(fù)數(shù)但是邏輯移位后不保證是負(fù)數(shù)
- Integer.toBinaryString的作用
可以把正型輸出為補(bǔ)碼杜恰。
原碼:是一種計(jì)算機(jī)中對(duì)數(shù)字的二進(jìn)制定點(diǎn)表示方法获诈。原碼表示法在數(shù)值前面增加了一位符號(hào)位(即最高位為符號(hào)位):正數(shù)該位為0仍源,負(fù)數(shù)該位為1(0有兩種表示:+0和-0),其余位表示數(shù)值的大小舔涎。
反碼:正數(shù)的反碼與其原碼相同笼踩;負(fù)數(shù)的反碼是對(duì)其原碼逐位取反,但符號(hào)位除外亡嫌。
反碼通常用來(lái)作為原碼求補(bǔ)碼或者補(bǔ)碼求源碼的過(guò)渡嚎于。
補(bǔ)碼:計(jì)算機(jī)中用補(bǔ)碼表示。
對(duì)于正數(shù)挟冠,補(bǔ)碼和原碼的表示相同
對(duì)于負(fù)數(shù)于购,原碼符號(hào)位不變, 數(shù)值部分按位取反知染,末位加1(即“取反加1”)此規(guī)則同樣用于補(bǔ)碼求原碼肋僧。
題目:變量a是一個(gè)64位有符號(hào)的整數(shù),初始值用16進(jìn)制表示為:0x7FFFFFFFFFFFFFFF;
變量b是一個(gè)64位有符號(hào)的整數(shù)控淡,初始值用16進(jìn)制表示為:0x8000000000000000嫌吠。
則a+b的結(jié)果用10進(jìn)制表示為多少?
理解:其中計(jì)算機(jī)中的數(shù)值用補(bǔ)碼表示掺炭,所以a和b都是補(bǔ)碼
0x7FFF,FFFF,FFFF,FFFF + 0x8000,0000,0000,0000 = 0xFFFF,FFFF,FFFF,FFFF
然后將 0xFFFF,FFFF,FFFF,FFFF轉(zhuǎn)為原碼(初符號(hào)位以外取反加1)等于0x1000辫诅,0000,0000,0001即為-1
詳細(xì)介紹請(qǐng)參考:http://www.cnblogs.com/wxdlut/p/5881865.htmlpublic class App { public static void main( String[] args ) { long a = 0x7FFFFFFFFFFFFFFFL; System.out.println(Long.toBinaryString(a)); long b = 0x8000000000000000L; System.out.println(Long.toBinaryString(b)); System.out.println(a+b); long c = a + b; System.out.println(Long.toBinaryString(c)); } }
- Switch能否用string做參數(shù)?
- equals與==的區(qū)別
- Java的四種引用涧狮,強(qiáng)弱軟虛炕矮,用到的場(chǎng)景。
- Hashcode的作用
- ArrayList者冤、LinkedList吧享、Vector的區(qū)別
- Collection包結(jié)構(gòu),與Collections的區(qū)別
- try catch finally譬嚣,try里有return钢颂,finally還執(zhí)行么?
- Excption與Error包結(jié)構(gòu)拜银。OOM你遇到過(guò)哪些情況殊鞭,SOF你遇到過(guò)哪些情況
- Java面向?qū)ο蟮娜齻€(gè)特征與含義
- Override和Overload的含義去區(qū)別
- Interface與abstract類(lèi)的區(qū)別
- Static class 與non static class的區(qū)別
- Java多態(tài)的實(shí)現(xiàn)原理
二遭垛、Java進(jìn)階
- 注解實(shí)現(xiàn)原理是什么?
- 能不能調(diào)用一個(gè)類(lèi)的私有方法操灿?為什么锯仪?
- JDK中有哪些設(shè)計(jì)模式的運(yùn)用?你的項(xiàng)目中用了哪些設(shè)計(jì)模式趾盐?TreeMap中Compartor用了什么設(shè)計(jì)模式庶喜?
- 設(shè)計(jì)模式的六大原則是什么?如何理解救鲤?
- 原則1:?jiǎn)我宦氊?zé)原則:不要存在多于一個(gè)導(dǎo)致類(lèi)變更的原因久窟。通俗的說(shuō),即一個(gè)類(lèi)只負(fù)責(zé)一項(xiàng)職責(zé)本缠。
- 原則2:里氏替換原則:子類(lèi)可以擴(kuò)展父類(lèi)的功能斥扛,但不能改變父類(lèi)原有的功能。
- 原則3:依賴(lài)倒置原則:高層模塊不應(yīng)該依賴(lài)低層模塊丹锹,二者都應(yīng)該依賴(lài)其抽象(接口)稀颁;抽象不應(yīng)該依賴(lài)細(xì)節(jié);細(xì)節(jié)應(yīng)該依賴(lài)抽象楣黍。
- 原則4:接口隔離原則:客戶端不應(yīng)該依賴(lài)它不需要的接口匾灶;一個(gè)類(lèi)對(duì)另一個(gè)類(lèi)的依賴(lài)應(yīng)該建立在最小的接口上。接口設(shè)計(jì)的過(guò)大或過(guò)小都不好租漂。
- 原則5:迪米特法則:一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象保持最少的了解阶女。迪米特法則又叫最少知道原則
- 原則6:開(kāi)閉原則:個(gè)軟件實(shí)體如類(lèi)、模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開(kāi)放窜锯,對(duì)修改關(guān)閉张肾。
- 總結(jié):?jiǎn)我宦氊?zé)原則告訴我們實(shí)現(xiàn)類(lèi)要職責(zé)單一;里氏替換原則告訴我們不要破壞繼承體系锚扎;依賴(lài)倒置原則告訴我們要面向接口編程吞瞪;接口隔離原則告訴我們?cè)谠O(shè)計(jì)接口的時(shí)候要精簡(jiǎn)單一;迪米特法則告訴我們要降低耦合驾孔。而開(kāi)閉原則是總綱芍秆,他告訴我們要對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉翠勉。
- 用過(guò)哪些設(shè)計(jì)模式妖啥?怎樣實(shí)現(xiàn)線程安全單例模式?
- 有哪些單例模式的實(shí)現(xiàn)方式对碌?
- 線程安不安全怎么理解荆虱?啟動(dòng)多個(gè)線程,如何知道他們都運(yùn)行完畢了?
- BIO,NIO,AIO區(qū)別是什怀读?Netty用的多嗎诉位?
- 簡(jiǎn)述Java內(nèi)存模型?新生代老年代有哪些垃圾回收算法菜枷?新生代老年代屬于堆還是棧苍糠?還知道哪些GC算法?創(chuàng)建大對(duì)象也是在新生代分配嗎啤誊?
- 為什么Java內(nèi)存模型中新生代和老年代采用GC算法不同岳瞭?
- 簡(jiǎn)述新生代老年代gc過(guò)程;
- 詳述JVM內(nèi)存分代機(jī)制蚊锹,并比較各個(gè)帶使用的回收算法和各個(gè)帶的特點(diǎn)瞳筏;說(shuō)說(shuō)分代回收的優(yōu)點(diǎn)有哪些?
- 說(shuō)說(shuō)新生代的算法中minor gc是什么枫耳?minor gc觸發(fā)條件是什么乏矾?老年代用了什么算法孟抗?說(shuō)說(shuō)標(biāo)記整理算法迁杨;full gc是否真正回收了廢棄對(duì)象。有哪些gc策略凄硼。你覺(jué)得你的項(xiàng)目中如果需要jvm調(diào)優(yōu)你會(huì)注重哪個(gè)分帶的調(diào)優(yōu)铅协,或者說(shuō)更注重哪種gc調(diào)優(yōu),為什么摊沉,具體怎么做
- TreeMap中元素怎么排序狐史,如果沒(méi)實(shí)現(xiàn)Comparator接口會(huì)怎么樣?
- 紅黑樹(shù),二叉樹(shù)说墨?紅黑樹(shù)是基于什么數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的骏全?紅黑樹(shù)可能會(huì)再轉(zhuǎn)為鏈表嗎(長(zhǎng)度低于6會(huì)轉(zhuǎn)回鏈表)
- 簡(jiǎn)述Socket長(zhǎng)連接短連接;當(dāng)連接出現(xiàn)異常你是怎么處理的?
- 如果CPU有8個(gè)核心尼斧,那么程序啟動(dòng)多少個(gè)線程相對(duì)合適?
- synchronized作用姜贡,原理及JDK6之后的優(yōu)化,與lock有哪些區(qū)別棺棵;你還知道哪些鎖楼咳?
- 鎖升級(jí):偏向鎖->輕量級(jí)鎖->重量級(jí)鎖
- Java中的同步機(jī)制,synchronized關(guān)鍵字烛恤,鎖(重入鎖)機(jī)制母怜,其他解決同步的方volatile關(guān)鍵字ThreadLocal類(lèi)的實(shí)現(xiàn)原理要懂。
- 什么是自旋鎖缚柏?
- 線程池苹熏,線程池等待隊(duì)列,線程池拒絕策略,死鎖產(chǎn)生原因轨域?
- 實(shí)現(xiàn)線程的方式缕陕?
- 鎖的等級(jí):方法鎖、對(duì)象鎖疙挺、類(lèi)鎖
- 寫(xiě)出生產(chǎn)者消費(fèi)者模式
- ThreadLocal的設(shè)計(jì)理念與作用
- ThreadPool用法與優(yōu)勢(shì)
- Concurrent包里的其他東西:ArrayBlockingQueue扛邑、CountDownLatch等等
- 線程對(duì)象的方法run和start區(qū)別在哪?
- 簡(jiǎn)述線程的狀態(tài)切換的狀態(tài)變化過(guò)程铐然;
- 簡(jiǎn)述:線程池蔬崩,線程池等待隊(duì)列,線程池拒絕策略
- 死鎖產(chǎn)生原因有哪些搀暑?
- 如果線程池執(zhí)行shutdown或shutdownNow沥阳,線程池中線程會(huì)中斷嗎,會(huì)出現(xiàn)什么異常自点,catch處理中該寫(xiě)些什么桐罕?
- 線程池有哪些參數(shù),各代表什么意思桂敛?
- 線程池中提供哪些隊(duì)列種類(lèi)功炮?
- 假如線程池核心池5,總池大小10术唬,有界隊(duì)列長(zhǎng)度10薪伏,現(xiàn)在有13個(gè)線程要用線程池運(yùn)行,說(shuō)下核心池和隊(duì)列中的線程情況粗仓;
- JDK中提供了哪幾種線程池的實(shí)現(xiàn)嫁怀?
- 用過(guò)哪些concurrent包下的類(lèi)?
- 簡(jiǎn)述什么是原子類(lèi)借浊,cas操作可能會(huì)存在什么問(wèn)題塘淑?
- 項(xiàng)目中有用到多線程,線程池嗎蚂斤,怎么用的存捺?
- jvm調(diào)優(yōu)有哪些切入點(diǎn)?
- 簡(jiǎn)述volatile關(guān)鍵字背后的實(shí)現(xiàn)原理橡淆;
- 簡(jiǎn)述Java反射機(jī)制和內(nèi)省機(jī)制召噩;
- 如何合理地估算線程池大小逸爵?
- 參考鏈接:http://ifeve.com/how-to-calculate-threadpool-size/
- 考慮cpu的個(gè)數(shù)具滴,期望cpu利用率, io密集型任務(wù)师倔, cpu密集型任務(wù)构韵,當(dāng)前系統(tǒng)是不是有其他的任務(wù)。
- 在《Java Concurrentcy in Practise》給出的經(jīng)驗(yàn)公式如下:
- N_threads = 線程個(gè)數(shù)
- N_cpu = CPU的數(shù)量
- U_cpu = 目標(biāo)CPU的使用率, (0<=Ucpu<=1)
- W/C = 等待時(shí)間和計(jì)算時(shí)間的比率
- 為保持處理器達(dá)到期望的使用率, 最優(yōu)的池的大小等于:
- N_threads = N_cpu * U_cpu * (1 + W/C)
- Java對(duì)象的內(nèi)存布局以及對(duì)象所需內(nèi)存大小計(jì)算
- Java中的鎖~隊(duì)列同步器
- 有沒(méi)有遇到中文亂碼問(wèn)題疲恢,如何解決的
- 你知道的開(kāi)源協(xié)議有哪些
- json和xml區(qū)別
- 用過(guò)哪些調(diào)試java內(nèi)存工具(https://www.nowcoder.com/discuss/3043)
- foreach與正常for循環(huán)效率對(duì)比
- 談?wù)勀銓?duì)Java淺克隆與深克隆的理解
- JVM
- 內(nèi)存模型以及分區(qū)凶朗,需要詳細(xì)到每個(gè)區(qū)放什么。
- 堆里面的分區(qū):Eden显拳,survival from to棚愤,老年代狸眼,各自的特點(diǎn)徘溢。
- 對(duì)象創(chuàng)建方法,對(duì)象的內(nèi)存分配猫十,對(duì)象的訪問(wèn)定位揍移。
- GC的兩種判定方法:引用計(jì)數(shù)與引用鏈次和。
- GC的三種收集方法:標(biāo)記清除、標(biāo)記整理那伐、復(fù)制算法的原理與特點(diǎn)踏施,分別用在什么地方,如果讓你優(yōu)化收集方法罕邀,有什么思路畅形?
- GC收集器有哪些?CMS收集器與G1收集器的特點(diǎn)燃少。
- Minor GC與Full GC分別在什么時(shí)候發(fā)生束亏?
- 幾種常用的內(nèi)存調(diào)試工具:jmap铃在、jstack阵具、jconsole。
- 類(lèi)加載的五個(gè)過(guò)程:加載定铜、驗(yàn)證阳液、準(zhǔn)備、解析揣炕、初始化帘皿。
- 先用javac Test.java進(jìn)行編譯。然后用java -XX:+TraceClassLoading Test畸陡。
- 然后就能在控制臺(tái)打印出一大串的log鹰溜。
- 在eclipse中查看類(lèi)加載過(guò)程步驟: 項(xiàng)目–>properties–>run/debug setting–>選擇目標(biāo)類(lèi)Test.java–>edit–>arguments–>VM arguments–> 輸入:-XX:+TraceClassLoading。
- 類(lèi)加載過(guò)程:
- 類(lèi)從被加載到虛擬機(jī)到虛擬機(jī)內(nèi)存中開(kāi)始丁恭,到卸載出內(nèi)存為止曹动,它的生命周期包括: 加載(Loading),驗(yàn)證(Verification)牲览,準(zhǔn)備(Preparation)墓陈,解析(Resolution), 初始化(Initialization),使用(Using)和卸載(Unloading)7個(gè)階段贡必。 其中驗(yàn)證兔港,準(zhǔn)備,解析這3個(gè)部分統(tǒng)稱(chēng)為鏈接(Linking)仔拟。 類(lèi)加載的過(guò)程:加載衫樊,驗(yàn)證,準(zhǔn)備利花,解析橡伞,初始化這5個(gè)過(guò)程
- 在加載階段,虛擬機(jī)完成以下3件事情:
- 通過(guò)一個(gè)類(lèi)的全限定名來(lái)獲取定義此類(lèi)的二進(jìn)制字節(jié)流
- 將這個(gè)字節(jié)流所代表的靜態(tài)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)
- 在內(nèi)存中生成一個(gè)代表這個(gè)類(lèi)的java.lang.Class對(duì)象晋被,作為方法區(qū)這個(gè)類(lèi)的各種數(shù)據(jù)訪問(wèn)的入口兑徘。
- 驗(yàn)證階段:驗(yàn)證目的是為了確保Class文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)規(guī)范,并且不會(huì)危害虛擬機(jī)自身安全羡洛。如果驗(yàn)證到輸入的字節(jié)流不符合Class文件的約束挂脑,會(huì)拋出java.lang.VerifyError異常或其子類(lèi)異常欲侮。驗(yàn)證階段大致分為4個(gè)階段完成:
- 文件格式驗(yàn)證:魔術(shù)崭闲,主次版本號(hào),常量池類(lèi)型等等
- 元數(shù)據(jù)驗(yàn)證:對(duì)字節(jié)碼描述的信息進(jìn)行語(yǔ)義分析威蕉,確保符號(hào)規(guī)范刁俭;比如:是否有父類(lèi),是否繼承final修飾的類(lèi)韧涨,是否實(shí)現(xiàn)了接口中的方法等等
- 字節(jié)碼驗(yàn)證:這個(gè)驗(yàn)證最復(fù)雜的部分牍戚,目的是通過(guò)數(shù)據(jù)流和控制流分析,確保程序語(yǔ)義合法虑粥,符合邏輯如孝。在第二階段元數(shù)據(jù)中數(shù)據(jù)類(lèi)型做完驗(yàn)證后,這個(gè)階段對(duì)類(lèi)的方法體進(jìn)行校驗(yàn)分析娩贷。
保證操作數(shù)棧的數(shù)據(jù)類(lèi)型與指令代碼序列可以配合工作第晰,不會(huì)出現(xiàn)操作數(shù)棧放置一個(gè)int類(lèi)型,使用時(shí)按long類(lèi)型加載本地變量表彬祖。 - 符合引用驗(yàn)證:發(fā)生在虛擬機(jī)將符號(hào)引用轉(zhuǎn)化為直接引用的時(shí)候茁瘦。比如符號(hào)引用中通過(guò)字符串描述的全限定名是否能查找到相應(yīng)的類(lèi),符號(hào)引用中的類(lèi)储笑,字段甜熔,方法的訪問(wèn)性是否可以被當(dāng)前類(lèi)方法。
符號(hào)引用驗(yàn)證的目的是確保解析動(dòng)作能正常執(zhí)行
對(duì)于虛擬機(jī)的類(lèi)加載機(jī)制來(lái)說(shuō)南蓬,驗(yàn)證階段是一個(gè)非常重要的纺非,但不是一定必要的階段哑了。(因?yàn)閷?duì)程序運(yùn)行期沒(méi)有影響)。
- 準(zhǔn)備階段: 準(zhǔn)備階段是正式為類(lèi)的變量分配內(nèi)存并設(shè)置類(lèi)變量初始值的階段烧颖,這些變量所使用的內(nèi)存都將在方法區(qū)中進(jìn)行分配弱左。注意:這時(shí)候進(jìn)行內(nèi)存分配的僅包括類(lèi)變量(被static修飾的變量),而不包括實(shí)例變量炕淮,這里所說(shuō)的初始值“通常情況”下是數(shù)值類(lèi)型的零值拆火。
相對(duì)“通常情況”會(huì)有一些特殊情況:如果類(lèi)字段的字段屬性存在ConstantValue屬性,那在準(zhǔn)備階段變量會(huì)被初始化為ConstantValue屬性所指定的值涂圆。比如:public static final int value = 123; 編譯時(shí)javac將會(huì)為value生成ConstantValue屬性们镜,在準(zhǔn)備階段虛擬機(jī)就會(huì)根據(jù)ConstantValue的設(shè)置將value賦值為123 - 解析階段: 解析階段是虛擬機(jī)將常量池的符合引用替換為直接引用的過(guò)程。 符合引用:符合引用字面量形式明確定義在Java虛擬機(jī)規(guī)范的Class文件格式中润歉。符合引用于虛擬機(jī)實(shí)現(xiàn)的內(nèi)存布局無(wú)關(guān)模狭。直接引用:直接引用是可以直接指向目標(biāo)的指針,相對(duì)偏移量或是一個(gè)能間接定位到目標(biāo)的句柄踩衩。直接引用和虛擬機(jī)實(shí)習(xí)的內(nèi)存布局相關(guān)嚼鹉。如果有了直接引用,目標(biāo)必定已經(jīng)存在內(nèi)存當(dāng)中驱富。 解析動(dòng)作主要針對(duì)類(lèi)或接口锚赤,字段,類(lèi)方法褐鸥, 接口方法的解析线脚。
- 初始化:類(lèi)的初始化是類(lèi)加載過(guò)程的最后一步,前面的類(lèi)加載過(guò)程中叫榕,除了在加載階段用戶應(yīng)用程序可以通過(guò)自定義類(lèi)加載器參與之外浑侥,其余動(dòng)作完全由虛擬機(jī)主導(dǎo)和控制。到了初始化階段翠霍,才真正開(kāi)始執(zhí)行類(lèi)中定義的Java程序代碼(或者說(shuō)是字節(jié)碼)锭吨。初始化階段是執(zhí)行類(lèi)構(gòu)造器方法的過(guò)程。 構(gòu)造器執(zhí)行時(shí)由編譯器自動(dòng)收集類(lèi)中所有類(lèi)變量的賦值動(dòng)作和靜態(tài)語(yǔ)句塊中的語(yǔ)句合并產(chǎn)生的寒匙,編譯器收集順序是由語(yǔ)句在原文件中出現(xiàn)的順序決定,靜態(tài)語(yǔ)句塊中只能訪問(wèn)到定義在靜態(tài)語(yǔ)句塊之前的變量躏将,定義在它之后的變量锄弱,在前面的靜態(tài)語(yǔ)句塊中可以賦值,但是不能訪問(wèn)祸憋。
- 雙親委派模型:Bootstrap ClassLoader会宪、Extension ClassLoader、ApplicationClassLoader蚯窥。
- 分派:靜態(tài)分派與動(dòng)態(tài)分派掸鹅。
- 面向?qū)ο蠛兔嫦蜻^(guò)程的區(qū)別
- 什么是泛型塞帐、為什么要使用以及泛型擦除
- Error、Exception區(qū)別
- 終止線程有幾種方式巍沙?終止線程標(biāo)記變量為什么是valotile類(lèi)型葵姥?
- 什么叫守護(hù)線程,用什么方法實(shí)現(xiàn)守護(hù)線程
- Java線程池技術(shù)及原理句携,如何實(shí)現(xiàn)一個(gè)線程池
- 常見(jiàn)的序列化協(xié)議有哪些
- 內(nèi)存溢出和內(nèi)存泄漏的區(qū)別
- ava內(nèi)存模型及各個(gè)區(qū)域的OOM榔幸,如何重現(xiàn)OOM,出現(xiàn)OOM如何解決
- 用什么工具可以查出內(nèi)存泄漏
- Java類(lèi)加載器及如何加載類(lèi)矮嫉,判斷兩個(gè)對(duì)象是否相等削咆。(雙親委派)
- 比較兩個(gè)類(lèi)是否“相等”,只有在這兩個(gè)類(lèi)是由同一個(gè)類(lèi)加載器加載它們才有意義蠢笋,否則拨齐,即使兩個(gè)類(lèi)來(lái)源同一個(gè)Class文件,被同一個(gè)虛擬機(jī)加載昨寞,只要加載它們的類(lèi)加載器不同奏黑,那這兩個(gè)類(lèi)就必定不相等。
- 雙親委派模型
- 啟動(dòng)類(lèi)加載器(Bootstrap ClassLoader)C++編寫(xiě)
- 擴(kuò)展類(lèi)加載器 (Extension ClassLoader)一般對(duì)應(yīng)jre\lib\ext
- 應(yīng)用程序類(lèi)加載器(Application ClassLoader)加載classpath指定的類(lèi)编矾,是最長(zhǎng)使用的一種加載器
- 看過(guò)哪些JDK源碼
- 詳述類(lèi)加載機(jī)制
- 什么是冪等性
- 有哪些JVM調(diào)優(yōu)經(jīng)驗(yàn)
-
Java多線程技術(shù)圖譜
三熟史、JavaWeb基礎(chǔ)
- Servlet和Jsp區(qū)別有哪些?如果沒(méi)有Servlet窄俏,Jsp怎么跟后端交互?
- JSP和Servlet的區(qū)別蹂匹;
- JSP的動(dòng)態(tài)include和靜態(tài)include;
- MVC概念凹蜈;
- 簡(jiǎn)述Servlet生命周期限寞;
- Tomcat在初始化中做了什么事?
- Tomcat調(diào)優(yōu)怎么做仰坦?切入點(diǎn)在哪里履植?
- SQL優(yōu)化有哪些切入點(diǎn)?
- SQL左連接右連接區(qū)別悄晃?
- 數(shù)據(jù)庫(kù)優(yōu)化喲哪些措施玫霎?
- 數(shù)據(jù)庫(kù)索引在什么時(shí)候使用?什么樣的字段適合建立索引妈橄?談?wù)勊饕牡讓訑?shù)據(jù)結(jié)構(gòu)庶近;
- 索引什么情況下會(huì)失效?聯(lián)合索引abc只用了a字段眷蚓,索引是否會(huì)生效鼻种?
- SQL交并差集是用來(lái)干什么的?
- 簡(jiǎn)述MySQL事務(wù)隔離級(jí)別沙热;
- JDBC連接步驟叉钥,Statement和PrepareStatement區(qū)別罢缸;
- 區(qū)別:
- Statement、PreparedStatement和CallableStatement都是接口(interface)投队。
- Statement繼承自Wrapper枫疆、PreparedStatement繼承自Statement、CallableStatement繼承自PreparedStatement蛾洛。
- Statement每次執(zhí)行sql語(yǔ)句养铸,數(shù)據(jù)庫(kù)都要執(zhí)行sql語(yǔ)句的編譯 , 最好用于僅執(zhí)行一次查詢并返回結(jié)果的情形轧膘,效率高于PreparedStatement钞螟。
- 各自的特點(diǎn)1
- Statement接口提供了執(zhí)行語(yǔ)句和獲取結(jié)果的基本方法;
- PreparedStatement接口添加了處理 IN 參數(shù)的方法谎碍;
- CallableStatement接口添加了處理 OUT 參數(shù)的方法鳞滨。
- 各自的特點(diǎn)2
- Statement:普通的不帶參的查詢SQL;支持批量更新,批量刪除;
- PreparedStatement:可變參數(shù)的SQL,編譯一次,執(zhí)行多次,效率高; 安全性好蟆淀,有效防止Sql注入等問(wèn)題; 支持批量更新,批量刪除;
- CallableStatement:繼承自PreparedStatement,支持帶參數(shù)的SQL操作; 支持調(diào)用存儲(chǔ)過(guò)程,提供了對(duì)輸出和輸入/輸出參數(shù)(INOUT)的支持;
- PreparedStatement是預(yù)編譯的拯啦,使用PreparedStatement有幾個(gè)好處
- 在執(zhí)行可變參數(shù)的一條SQL時(shí),PreparedStatement比Statement的效率高熔任,因?yàn)镈BMS預(yù)編譯一條SQL當(dāng)然會(huì)比多次編譯一條SQL的效率要高褒链。
- 安全性好,有效防止Sql注入等問(wèn)題疑苔。
- 對(duì)于多次重復(fù)執(zhí)行的語(yǔ)句甫匹,使用PreparedStament效率會(huì)更高一點(diǎn),并且在這種情況下也比較適合使用batch惦费;
- 代碼的可讀性和可維護(hù)性兵迅。
- 區(qū)別:
- 項(xiàng)目中數(shù)據(jù)庫(kù)事務(wù)控制你們是怎么做的?
- 什么是存儲(chǔ)過(guò)程薪贫,在什么時(shí)候使用恍箭?
- MySQL有哪些存儲(chǔ)引擎?各自特點(diǎn)
- 樂(lè)觀鎖與悲觀鎖瞧省。使用場(chǎng)景有何差異扯夭?怎么實(shí)現(xiàn)樂(lè)觀鎖?
- 樂(lè)觀鎖與悲觀鎖:二者都是正如其名臀突,樂(lè)觀鎖對(duì)待競(jìng)爭(zhēng)資源保持樂(lè)觀的態(tài)度勉抓,認(rèn)為資源不是競(jìng)爭(zhēng)激烈的資源,每次操作之前都要進(jìn)行比對(duì)候学;而悲觀鎖則認(rèn)為競(jìng)爭(zhēng)資源競(jìng)爭(zhēng)異常激烈,只要操作纵散,立馬加鎖梳码,直到資源的操作完畢才釋放鎖隐圾;
- 樂(lè)觀鎖則適用于讀多寫(xiě)少,并發(fā)沖突少的場(chǎng)景掰茶。悲觀鎖比較適合強(qiáng)一致性的場(chǎng)景暇藏,但效率比較低,特別是讀的并發(fā)低濒蒋。
- 在MySQL中盐碱,樂(lè)觀鎖的實(shí)現(xiàn)一般需要借助于操作表的一個(gè)字段,可以是額外添加的沪伙,如
version
或timestamp
瓮顽,也可以是現(xiàn)有的字段,但是一般選取第一種方案围橡,我們經(jīng)常采用的是timestamp的方案暖混;每次在更新數(shù)據(jù)之前先要邏輯判斷這個(gè)字段是否和之前查到的一樣,一樣則進(jìn)行相應(yīng)的更新操作翁授,否則進(jìn)行睡眠指定的時(shí)間拣播,一般是毫秒級(jí)別重復(fù)進(jìn)行如上操作;
- MySQL 索引原理收擦。為什么索引一部分放到內(nèi)存贮配,一部分放到硬盤(pán)上? MySQL數(shù)據(jù)庫(kù)索引原理
- MySQL有哪些存儲(chǔ)引擎?各自特點(diǎn) ?MySQL默認(rèn)的存儲(chǔ)引擎是什么塞赂?
- MySQL5.5以后默認(rèn)使用InnoDB存儲(chǔ)引擎泪勒,其中InnoDB和BDB提供事務(wù)安全表
四、JavaWeb常用框架
- 簡(jiǎn)述Spring IoC减途,AOP作用和原理酣藻;
- 簡(jiǎn)述SpringMVC執(zhí)行流程;SpringMVC有什么優(yōu)點(diǎn)鳍置?為什么要用它辽剧?SpringMVC和Struts2區(qū)別有哪些?
- Spring Bean是單例嗎税产?單例bean是怎么實(shí)現(xiàn)的怕轿?Spring的Bean還有哪些其他模式?
- 簡(jiǎn)述SpringMVC獲取請(qǐng)求參數(shù)的方式有哪些辟拷?原理是什么撞羽?
- SpringMVC控制器中定義全局HashMap,它是否是線程安全的衫冻,為什么诀紊?
- 若想要在某些自己指定的某些方法前后打印日志怎么實(shí)現(xiàn)?
- 過(guò)濾器和攔截器的區(qū)別隅俘?
- Spring的BeanFactory和FactoryBean有什么區(qū)別邻奠?
- 兩個(gè)線程間隔輸出字符怎么實(shí)現(xiàn)笤喳?
- Java線程阻塞調(diào)用wait函數(shù)和sleep區(qū)別和聯(lián)系,還有函數(shù)yield碌宴,notify等的作用杀狡。
- Spring中有幾種注入Bean的方式?
- Struts中請(qǐng)求處理過(guò)程贰镣;
- SpringMVC與Struts2區(qū)別呜象;
- Hibernate/Ibatis兩者的區(qū)別;
- Hibernate一級(jí)和二級(jí)緩存碑隆;
- Hibernate實(shí)現(xiàn)集群部署恭陡;
- Hibernate如何實(shí)現(xiàn)聲明式事務(wù);
- 簡(jiǎn)述Hibernate常見(jiàn)優(yōu)化策略干跛;
- 優(yōu)化Hibernate所鼓勵(lì)的7大措施:
- 盡量使用many-to-one子姜,避免使用單項(xiàng)one-to-many
- 靈活使用單向one-to-many
- 不用一對(duì)一,使用多對(duì)一代替一對(duì)一
- 配置對(duì)象緩存楼入,不使用集合緩存
- 一對(duì)多使用Bag 多對(duì)一使用Set
- 繼承使用顯示多態(tài) HQL:from object polymorphism="exlicit" 避免查處所有對(duì)象
- 消除大表哥捕,使用二級(jí)緩存
- Spring如何實(shí)現(xiàn)AOP和IOC
- Spring bean注入方式
- Spring的事務(wù)管理(推薦看Spring的源碼)
- Spring事務(wù)的傳播特性
- springmvc原理
- springmvc用過(guò)哪些注解
- Restful有幾種請(qǐng)求
- Restful好處
- Tomcat,Apache嘉熊,JBoss的區(qū)別
- memcached和redis的區(qū)別
五遥赚、Java高級(jí)框架
- 你是怎么理解Nginx的?
- 為什么要用redis;redis有支持哪些數(shù)據(jù)結(jié)構(gòu)阐肤?
- zookeeper
- 消息中間件
- 分布式
- 集群
- 微服務(wù)
- 相比于如memcached,mongodb有什么優(yōu)勢(shì)
- 如何理解分布式鎖
- 分布式CAP了解嗎凫佛?
- 開(kāi)發(fā)過(guò)分布式框架?怎么實(shí)現(xiàn)分布式事務(wù)孕惜?
- 是否了解過(guò)高性能隊(duì)列Disruptor愧薛?
參考:高性能隊(duì)列——Disruptor
六、解決問(wèn)題
- 線上系統(tǒng)每天會(huì)收到20萬(wàn)級(jí)的數(shù)據(jù)衫画,一個(gè)月會(huì)有百萬(wàn)條毫炉,并且還會(huì)遞增,你如何設(shè)計(jì)數(shù)據(jù)庫(kù)削罩?(分庫(kù)分表瞄勾,建立索引) 分庫(kù)分表按什么規(guī)則分?如果查詢字段不是分庫(kù)分表的規(guī)則字段弥激,怎么辦进陡?(分庫(kù)分表多維度查詢) Oracle分頁(yè)的SQL關(guān)鍵字是什么?(rownum)
- 高并發(fā)情況下怎么降低服務(wù)器壓力(暫不從增加服務(wù)器和硬件提升層面考慮)微服,方案解決問(wèn)題:
- 假如servlet處理一個(gè)請(qǐng)求需要0.4秒趾疚,那么處理100請(qǐng)求大概需要多久,為什么。同時(shí)處理1000個(gè)請(qǐng)求導(dǎo)致服務(wù)器壓力過(guò)大崩潰怎么解決盗蟆?
- 線上系統(tǒng)造成服務(wù)器cpu占用率過(guò)高問(wèn)題(網(wǎng)上有解決方案)
- 秒殺系統(tǒng)少賣(mài)超賣(mài)問(wèn)題怎么處理(網(wǎng)上有解決方案)
- 有個(gè)業(yè)務(wù)場(chǎng)景戈二,通過(guò)第三方工具收集到大概百萬(wàn)條手機(jī)號(hào)舒裤,存儲(chǔ)到文本中喳资,文本中每行一個(gè)號(hào)碼。我們的數(shù)據(jù)庫(kù)中會(huì)存每個(gè)號(hào)碼對(duì)應(yīng)的會(huì)員等級(jí)信息(也有可能這個(gè)號(hào)碼在數(shù)據(jù)庫(kù)中不存在,那么他就是新用戶)腾供。按會(huì)員等級(jí)給號(hào)碼發(fā)送不同內(nèi)容的信息仆邓,新號(hào)碼發(fā)送邀請(qǐng)信息。設(shè)計(jì)一個(gè)方案伴鳖,怎么做效率最高(數(shù)據(jù)庫(kù)數(shù)據(jù)量很大)
- 瀏覽器如何實(shí)現(xiàn)免登陸之類(lèi)的功能节值,cookie和session的聯(lián)系和區(qū)別以及其作用;
- 寫(xiě)算法榜聂。找到最大子數(shù)組的start,和end下標(biāo)
- 5升桶3升桶搞4升水
面試及學(xué)習(xí)建議
基礎(chǔ)->spring/springmvc/mybatis/數(shù)據(jù)庫(kù)搞疗、緩存->消息中間件(activemq、kafka...)->(后面的僅代表個(gè)人看法须肆,未知領(lǐng)域...)springboot匿乃、微服務(wù)、docker/分布式豌汇、zookeeper幢炸、rpc/大數(shù)據(jù)相關(guān))
說(shuō)說(shuō)紅黑樹(shù),它是基于什么數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)的(紅黑樹(shù)了解不深拒贱,只是大致說(shuō)了下思想-旋轉(zhuǎn)宛徊、平衡、大小比較逻澳。(我感覺(jué)很難闸天,有空得靜下心來(lái)好好研究))。紅黑樹(shù)可能會(huì)再轉(zhuǎn)為鏈表嗎(答:長(zhǎng)度低于8會(huì)轉(zhuǎn)回鏈表 問(wèn):你確定是8而不是6 答:好像是6... (hashmap的看點(diǎn)真的很多斜做,回去看了源碼真的是6苞氮,而且擴(kuò)容時(shí)紅黑樹(shù)變化很復(fù)雜,暫時(shí)看不懂))陨享。說(shuō)下hashmap put的過(guò)程(答:key的hashcode高16位與低16位異或運(yùn)算得到新的hash葱淳,為了讓數(shù)據(jù)(特別是在當(dāng)前容量不大的情況下)散列更均勻,然后把異或計(jì)算出的新hash與此時(shí)的hashmap容量-1做&運(yùn)算抛姑,得到插入下標(biāo)赞厕。問(wèn):為什么要做&運(yùn)算,還有什么方式定硝。答:二進(jìn)制運(yùn)算速度快皿桑,還可以取模。之后如果下標(biāo)位數(shù)組無(wú)數(shù)據(jù)則直接插入,如果有數(shù)據(jù)則鏈表往下逐個(gè)進(jìn)行hash比較诲侮,如果產(chǎn)生hash碰撞再進(jìn)行==或者equals比較key是否一樣镀虐,一樣則覆蓋原數(shù)據(jù),否則添加到鏈表后面沟绪。問(wèn):發(fā)生hash沖突怎么辦 答:剛剛說(shuō)了(重復(fù))問(wèn):你確定是添加到鏈表后面嗎 答:確定(我懷疑他jdk8的hashmap沒(méi)看全(jdk7是新元素插入至鏈表頭部的)還問(wèn)了產(chǎn)生hash沖突后為什么還會(huì)比較原來(lái)key的hashcode刮便,表示沒(méi)聽(tīng)懂,看了源碼也沒(méi)發(fā)現(xiàn)有再次比較的過(guò)程绽慈,而且之后也重復(fù)問(wèn)rehash后的元素具體去向問(wèn)題(1.7和1.8元素rehash后元素去向是不同的)恨旱,還有擴(kuò)容問(wèn)題,感覺(jué)他對(duì)jdk8的hashmap和1.7的有點(diǎn)混淆(還好我沒(méi)怎么看jdk7坝疼,不過(guò)如果jdk7也看明白了搜贤,再說(shuō)明與1.8的區(qū)別之后估計(jì)會(huì)大大加分吧,有點(diǎn)遺憾))钝凶。繼續(xù)仪芒,當(dāng)hashmap中數(shù)據(jù)量超過(guò)當(dāng)前容量*擴(kuò)容因子(默認(rèn)0.75)則擴(kuò)容為原來(lái)的2倍,問(wèn):還有什么要求 答:好像沒(méi)了 問(wèn):當(dāng)前插入的位置上沒(méi)有元素就不擴(kuò)容吧 答:哦哦耕陷。(其實(shí)不然掂名,他說(shuō)的是jdk7的情況,jdk8沒(méi)有這個(gè)要求啃炸。當(dāng)時(shí)要是知道7和8的區(qū)別铆隘,指出這點(diǎn),那就是亮點(diǎn)了南用,再次遺憾))膀钠。為什么是2次冪擴(kuò)容。(答:我覺(jué)得有3點(diǎn)因素裹虫。2進(jìn)制運(yùn)算快肿嘲;hash與當(dāng)前容量-1做&運(yùn)算很快且很巧妙地獲得元素下標(biāo);擴(kuò)容后能巧妙地重新分配元素位置)說(shuō)下擴(kuò)容的rehash筑公,擴(kuò)容后的部分節(jié)點(diǎn)數(shù)據(jù)會(huì)重新定位雳窟,具體規(guī)則是hash&原容量,得到無(wú)非兩個(gè)結(jié)果:0和1匣屡,如果是0則該元素所在下標(biāo)位置不動(dòng)封救,如果是1則將該元素放置原位置擴(kuò)容后的對(duì)應(yīng)位置(假如原先容量為16,元素位置在數(shù)組下標(biāo)14的位置捣作,則擴(kuò)容后容量為32誉结,該元素移動(dòng)到數(shù)組下標(biāo)30的位置(即原索引+原容量位置)。當(dāng)時(shí)沒(méi)這點(diǎn)解釋的不夠準(zhǔn)確券躁,有瑕疵)惩坑。為什么看hashmap源碼掉盅,你覺(jué)得看了后對(duì)你有什么好處(答:比較喜歡探究(其實(shí)是近期面試才認(rèn)真看的...)。知道了計(jì)算機(jī)位運(yùn)算速度會(huì)比其它數(shù)學(xué)運(yùn)算快以舒;學(xué)習(xí)了它的思想對(duì)我思考問(wèn)題方式有提升(能吹多少盡量吹多少)趾痘;擴(kuò)容是一個(gè)費(fèi)性能的事,如果知道集合中大致會(huì)存多少元素最好給它一個(gè)初始容量)蔓钟,如果你知道里面會(huì)存100個(gè)左右數(shù)據(jù)永票,你會(huì)給它多大初始容量 (答:128) 它是線程安全的嗎(答:不是,jdk1.8多線程情況下可能會(huì)造成數(shù)據(jù)丟失奋刽,1.8之前更可能造成死循環(huán))瓦侮,線程安全的map有什么(答:hashtable,concurrentHashMap,前者已經(jīng)被后者替代了,效率更高)佣谐,說(shuō)說(shuō)concurrentHashMap,默認(rèn)容量多少(答:16方妖。只是了解狭魂,太復(fù)雜了,沒(méi)細(xì)看党觅,只知道jdk1.8之前采用分段鎖方式處理雌澄,1.8之后采用cas樂(lè)觀鎖的方式來(lái)操作)。其它集合類(lèi)了解嗎(hashSet,treeSet,treeMap,都解釋的相對(duì)明白牵辣,篇幅過(guò)長(zhǎng)六敬,不細(xì)說(shuō)了),它們是否允許插入空值(treeSet,treeMap不可以)使用treeMap有什么需要注意的 (其中的元素要實(shí)現(xiàn)comparator接口)
鏈接:https://www.nowcoder.com/discuss/36782
來(lái)源:畔诙客網(wǎng)
一面(順序可能有適當(dāng)修改):
1、一個(gè)數(shù)組,有正有負(fù)畦浓,把正的移到右邊,負(fù)的移到左邊检疫。
2讶请、判斷一個(gè)鏈表是否有環(huán)(我回答快慢指針,因此引出下一個(gè)問(wèn)題)
3屎媳、假設(shè)一個(gè)節(jié)點(diǎn)為100的環(huán)形單鏈表夺溢,你這方法要走多少步判斷出有環(huán),99個(gè)節(jié)點(diǎn)呢烛谊?
4风响、tcp三次握手的過(guò)程?
5晒来、進(jìn)程與線程的區(qū)別钞诡?
6郑现、說(shuō)說(shuō)你了解的http狀態(tài)碼,http請(qǐng)求方法荧降?
7接箫、簡(jiǎn)單說(shuō)下銀行家算法?
8朵诫、項(xiàng)目等相關(guān)辛友。
9、實(shí)現(xiàn)一個(gè)生產(chǎn)者和消費(fèi)者剪返?
然后讓我在房間等會(huì)废累,過(guò)了幾分鐘,二面面試官進(jìn)來(lái)脱盲。
二面:
1邑滨、dubbo怎么實(shí)現(xiàn)異步的?(由于項(xiàng)目使用了)
2钱反、dubbo底層怎么通信的掖看?
3、進(jìn)程和線程的區(qū)別面哥?linux有進(jìn)程和線程的區(qū)分嗎哎壳?
4、中斷和異常是什么尚卫?有什么區(qū)別归榕?
5、tcp三次握手和四次揮手吱涉,兩次握手會(huì)怎么樣刹泄?
6、說(shuō)說(shuō)arp協(xié)議邑飒,nat協(xié)議循签,局域網(wǎng)是怎么通信的?
7疙咸、ip地址和mac地址區(qū)別县匠?
8、虛擬內(nèi)存和虛擬地址是什么撒轮?
9乞旦、死鎖的必要條件?舉一個(gè)死鎖的例子题山,怎么避免死鎖兰粉,怎么解決死鎖?
10顶瞳、hashmap玖姑、concurrenthashmap愕秫、hashtable?
11焰络、項(xiàng)目戴甩,具體就不說(shuō)了。
12闪彼、說(shuō)下dns的過(guò)程甜孤?
13、最小堆的定義畏腕?最小堆的插入與刪除的全過(guò)程缴川?
14、紅黑樹(shù)的定義描馅?為什么是平衡樹(shù)把夸?怎么維護(hù)平衡?
15流昏、B+樹(shù)的定義扎即?為什么要用b+樹(shù),而不用平衡二叉樹(shù)况凉?
16、聚集索引和非聚集索引的區(qū)別各拷?
17刁绒、synchronized的原理?
18烤黍、synchronized和lock的區(qū)別知市?
19、如果美團(tuán)給了你offer速蕊,你實(shí)習(xí)公司又轉(zhuǎn)正了嫂丙,你還來(lái)嗎?
然后帶我出去规哲,說(shuō)等會(huì)不在這間房間跟啤,然后路上問(wèn)我實(shí)習(xí)的部門(mén)leader是誰(shuí),臥槽唉锌,他認(rèn)識(shí)我leader隅肥。很是尷尬。等了幾分鐘袄简,三面面試官帶我去另一個(gè)地方面試腥放。
三面(最難,問(wèn)的很深入):
1绿语、排序算法的穩(wěn)定性是指什么秃症?
2候址、說(shuō)說(shuō)常見(jiàn)排序算法的穩(wěn)定性?選擇排序?yàn)槭裁床环€(wěn)定种柑?歸并為什么是穩(wěn)定的岗仑?
3、講一下堆排序的全過(guò)程(這里面試官對(duì)每一個(gè)參數(shù)都會(huì)問(wèn)清楚)莹规?
4赔蒲、你知道的設(shè)計(jì)模式(我回答單例,工廠良漱,觀察者舞虱,裝飾者,因此引出更多問(wèn)題)母市?
5矾兜、你會(huì)的單例(我回答懶漢,惡漢患久,靜態(tài)內(nèi)部類(lèi)椅寺,枚舉,雙重檢查)蒋失?
6返帕、說(shuō)說(shuō)雙重檢查,volatile關(guān)鍵字的作用篙挽,因此也問(wèn)了內(nèi)存可見(jiàn)性和重排序荆萤?
7、說(shuō)說(shuō)原子類(lèi)實(shí)現(xiàn)原理铣卡?(cas)链韭?
8、說(shuō)說(shuō)cas需要哪些參數(shù)煮落,操作系統(tǒng)對(duì)應(yīng)的命令是什么敞峭?為什么能保證原子性?
9蝉仇、volatile和cas有什么關(guān)聯(lián)旋讹?什么時(shí)候可以互相替代?(一臉悶逼)
10量淌、觀察者模式有什么用骗村?怎么實(shí)現(xiàn)的?
11呀枢、java類(lèi)庫(kù)那個(gè)是用裝飾者模式(io)胚股?
12、裝飾著模式和代理模式有什么區(qū)別裙秋?(一臉懵逼)
13琅拌、給你一個(gè)64G的內(nèi)存缨伊,你會(huì)怎么設(shè)置堆大小进宝?
14刻坊、說(shuō)說(shuō)cms收集器的過(guò)程?
15党晋、平時(shí)線上項(xiàng)目出現(xiàn)問(wèn)題怎么排查谭胚?
16、hash沖突有哪些解決方法未玻?簡(jiǎn)單說(shuō)下再哈希法灾而?怎么保證多個(gè)hash函數(shù)不會(huì)出現(xiàn)死循環(huán)?(很懵逼)
17扳剿、類(lèi)加載機(jī)制旁趟?怎么破壞單例(這里應(yīng)該想讓我用類(lèi)加載機(jī)制來(lái)破壞)?
DBMS對(duì)數(shù)據(jù)庫(kù)的保護(hù)通過(guò)4個(gè)方面來(lái)實(shí)現(xiàn):
數(shù)據(jù)庫(kù)的恢復(fù)
數(shù)據(jù)庫(kù)的并發(fā)控制
數(shù)據(jù)庫(kù)的完整性控制
數(shù)據(jù)庫(kù)安全性控制
DBMS中實(shí)現(xiàn)事務(wù)持久性的子系統(tǒng)是恢復(fù)管理子系統(tǒng)庇绽。
大多數(shù) JVM 將內(nèi)存區(qū)域劃分為
- Method Area(Non-Heap)(方法區(qū)) ,
- Heap(堆) ,
- Program Counter Register(程序計(jì)數(shù)器) ,
- VM Stack(虛擬機(jī)棧锡搜,也有翻譯成JAVA 方法棧的),
- Native Method Stack ( 本地方法棧 )
其中Method Area 和 Heap 是線程共享的 ,VM Stack瞧掺,Native Method Stack 和Program Counter Register 是非線程共享的耕餐。為什么分為 線程共享和非線程共享的呢?請(qǐng)繼續(xù)往下看。
首先我們熟悉一下一個(gè)一般性的 Java 程序的工作過(guò)程辟狈。一個(gè) Java 源程序文件蛾方,會(huì)被編譯為字節(jié)碼文件(以 class 為擴(kuò)展名),每個(gè)java程序都需要運(yùn)行在自己的JVM上上陕,然后告知 JVM 程序的運(yùn)行入口,再被 JVM 通過(guò)字節(jié)碼解釋器加載運(yùn)行拓春。那么程序開(kāi)始運(yùn)行后释簿,都是如何涉及到各內(nèi)存區(qū)域的呢?
概括地說(shuō)來(lái)硼莽,JVM初始運(yùn)行的時(shí)候都會(huì)分配好 Method Area(方法區(qū)) 和Heap(堆) 庶溶,而JVM 每遇到一個(gè)線程,就為其分配一個(gè) Program Counter Register(程序計(jì)數(shù)器) , VM Stack(虛擬機(jī)棧)和Native Method Stack (本地方法棧)懂鸵, 當(dāng)線程終止時(shí)偏螺,三者(虛擬機(jī)棧,本地方法棧和程序計(jì)數(shù)器)所占用的內(nèi)存空間也會(huì)被釋放掉匆光。這也是為什么我把內(nèi)存區(qū)域分為線程共享和非線程共享的原因套像,非線程共享的那三個(gè)區(qū)域的生命周期與所屬線程相同,而線程共享的區(qū)域與JAVA程序運(yùn)行的生命周期相同终息,所以這也是系統(tǒng)垃圾回收的場(chǎng)所只發(fā)生在線程共享的區(qū)域(實(shí)際上對(duì)大部分虛擬機(jī)來(lái)說(shuō)知發(fā)生在Heap上)的原因夺巩。
事務(wù)屬性的種類(lèi): 傳播行為贞让、隔離級(jí)別、只讀和事務(wù)超時(shí)
a) 傳播行為定義了被調(diào)用方法的事務(wù)邊界柳譬。
傳播行為 | 意義 |
---|---|
PROPERGATION_MANDATORY | 表示方法必須運(yùn)行在一個(gè)事務(wù)中喳张,如果當(dāng)前事務(wù)不存在,就拋出異常 |
PROPAGATION_NESTED | 表示如果當(dāng)前事務(wù)存在美澳,則方法應(yīng)該運(yùn)行在一個(gè)嵌套事務(wù)中销部。否則,它看起來(lái)和 PROPAGATION_REQUIRED 看起來(lái)沒(méi)什么倆樣 |
PROPAGATION_NEVER | 表示方法不能運(yùn)行在一個(gè)事務(wù)中制跟,否則拋出異常 |
PROPAGATION_NOT_SUPPORTED | 表示方法不能運(yùn)行在一個(gè)事務(wù)中舅桩,如果當(dāng)前存在一個(gè)事務(wù),則該方法將被掛起 |
PROPAGATION_REQUIRED | 表示當(dāng)前方法必須運(yùn)行在一個(gè)事務(wù)中凫岖,如果當(dāng)前存在一個(gè)事務(wù)江咳,那么該方法運(yùn)行在這個(gè)事務(wù)中,否則哥放,將創(chuàng)建一個(gè)新的事務(wù) |
PROPAGATION_REQUIRES_NEW | 表示當(dāng)前方法必須運(yùn)行在自己的事務(wù)中歼指,如果當(dāng)前存在一個(gè)事務(wù),那么這個(gè)事務(wù)將在該方法運(yùn)行期間被掛起 |
PROPAGATION_SUPPORTS | 表示當(dāng)前方法不需要運(yùn)行在一個(gè)是事務(wù)中甥雕,但如果有一個(gè)事務(wù)已經(jīng)存在踩身,該方法也可以運(yùn)行在這個(gè)事務(wù)中 |
b) 隔離級(jí)別
在操作數(shù)據(jù)時(shí)可能帶來(lái) 3 個(gè)副作用,分別是臟讀社露、不可重復(fù)讀挟阻、幻讀。為了避免這 3 中副作用的發(fā)生峭弟,在標(biāo)準(zhǔn)的 SQL 語(yǔ)句中定義了 4 種隔離級(jí)別附鸽,分別是未提交讀、已提交讀瞒瘸、可重復(fù)讀坷备、可序列化。而在 spring 事務(wù)中提供了 5 種隔離級(jí)別來(lái)對(duì)應(yīng)在 SQL 中定義的 4 種隔離級(jí)別情臭,如下:
隔離級(jí)別 | 意義 |
---|---|
ISOLATION_DEFAULT | 使用后端數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別 |
ISOLATION_READ_UNCOMMITTED | 允許讀取未提交的數(shù)據(jù)(對(duì)應(yīng)未提交讀)省撑,可能導(dǎo)致臟讀、不可重復(fù)讀俯在、幻讀 |
ISOLATION_READ_COMMITTED | 允許在一個(gè)事務(wù)中讀取另一個(gè)已經(jīng)提交的事務(wù)中的數(shù)據(jù)(對(duì)應(yīng)已提交讀)竟秫。可以避免臟讀跷乐,但是無(wú)法避免不可重復(fù)讀和幻讀 |
ISOLATION_REPEATABLE_READ | 一個(gè)事務(wù)不可能更新由另一個(gè)事務(wù)修改但尚未提交(回滾)的數(shù)據(jù)(對(duì)應(yīng)可重復(fù)讀)肥败。可以避免臟讀和不可重復(fù)讀,但無(wú)法避免幻讀 |
ISOLATION_SERIALIZABLE | 這種隔離級(jí)別是所有的事務(wù)都在一個(gè)執(zhí)行隊(duì)列中拙吉,依次順序執(zhí)行潮孽,而不是并行(對(duì)應(yīng)可序列化)】昵可以避免臟讀往史、不可重復(fù)讀、幻讀佛舱。但是這種隔離級(jí)別效率很低椎例,因此,除非必須请祖,否則不建議使用订歪。 |
c) 只讀
- 如果在一個(gè)事務(wù)中所有關(guān)于數(shù)據(jù)庫(kù)的操作都是只讀的,也就是說(shuō)肆捕,這些操作只讀取數(shù)據(jù)庫(kù)中的數(shù)據(jù)刷晋,而并不更新數(shù)據(jù),那么應(yīng)將事務(wù)設(shè)為只讀模式( READ_ONLY_MARKER ) , 這樣更有利于數(shù)據(jù)庫(kù)進(jìn)行優(yōu)化 慎陵。因?yàn)橹蛔x的優(yōu)化措施是事務(wù)啟動(dòng)后由數(shù)據(jù)庫(kù)實(shí)施的眼虱,因此,只有將那些具有可能啟動(dòng)新事務(wù)的傳播行為 (PROPAGATION_NESTED 席纽、 PROPAGATION_REQUIRED 捏悬、 PROPAGATION_REQUIRED_NEW) 的方法的事務(wù)標(biāo)記成只讀才有意義。
- 如果使用 Hibernate 作為持久化機(jī)制润梯,那么將事務(wù)標(biāo)記為只讀后过牙,會(huì)將 Hibernate 的 flush 模式設(shè)置為 FULSH_NEVER, 以告訴 Hibernate 避免和數(shù)據(jù)庫(kù)之間進(jìn)行不必要的同步,并將所有更新延遲到事務(wù)結(jié)束纺铭。
d) 事務(wù)超時(shí)
- 如果一個(gè)事務(wù)長(zhǎng)時(shí)間運(yùn)行寇钉,這時(shí)為了盡量避免浪費(fèi)系統(tǒng)資源,應(yīng)為這個(gè)事務(wù)設(shè)置一個(gè)有效時(shí)間舶赔,使其等待數(shù)秒后自動(dòng)回滾摧莽。與設(shè)置“只讀”屬性一樣,事務(wù)有效屬性也需要給那些具有可能啟動(dòng)新事物的傳播行為的方法的事務(wù)標(biāo)記成只讀才有意義顿痪。
Servlet 與 CGI 的比較
- 和CGI程序一樣,Servlet可以響應(yīng)用戶的指令(提交一個(gè)FORM等等)油够,也可以象CGI程序一樣蚁袭,收集用戶表單的信息并給予動(dòng)態(tài)反饋(簡(jiǎn)單的注冊(cè)信息錄入和檢查錯(cuò)誤)。然而石咬,Servlet的機(jī)制并不僅僅是這樣簡(jiǎn)單的與用戶表單進(jìn)行交互揩悄。傳統(tǒng)技術(shù)中,動(dòng)態(tài)的網(wǎng)頁(yè)建立和顯示都是通過(guò)CGI來(lái)實(shí)現(xiàn)的鬼悠,但是删性,有了Servlet,您可以大膽的放棄所有CGI(perl?php?甚至asp!)亏娜,利用Servlet代替CGI,進(jìn)行程序編寫(xiě)。
- 對(duì)比一:性能
- 當(dāng)用戶瀏覽器發(fā)出一個(gè)Http/CGI的請(qǐng)求蹬挺,或者說(shuō) 調(diào)用一個(gè)CGI程序的時(shí)候维贺,服務(wù)器端就要新啟用一個(gè)進(jìn)程 (而且是每次都要調(diào)用),調(diào)用CGI程序越多(特別是訪問(wèn)量高的時(shí)候)巴帮,就要消耗系統(tǒng)越多的處理時(shí)間溯泣,只剩下越來(lái)越少的系統(tǒng)資源,對(duì)于用戶來(lái)說(shuō)榕茧,只能是漫長(zhǎng)的等待服務(wù)器端的返回頁(yè)面了垃沦,這對(duì)于電子商務(wù)激烈發(fā)展的今天來(lái)說(shuō),不能不說(shuō)是一種技術(shù)上的遺憾用押。
- Servlet充分發(fā)揮了服務(wù)器端的資源并高效的利用肢簿。每次調(diào)用Servlet時(shí)并不是新啟用一個(gè)進(jìn)程 ,而是在一個(gè)Web服務(wù)器的進(jìn)程敏感詞享和分離線程蜻拨,而線程最大的好處在于可以共享一個(gè)數(shù)據(jù)源池充,使系統(tǒng)資源被有效利用。
- 對(duì)比二:平臺(tái)環(huán)境的敏感性
- 傳統(tǒng)的CGI程序官觅,不具備平臺(tái)無(wú)關(guān)性特征纵菌,系統(tǒng)環(huán)境發(fā)生變化,CGI程序就要癱瘓休涤,
- Servlet具備Java的平臺(tái)無(wú)關(guān)性咱圆,在系統(tǒng)開(kāi)發(fā)過(guò)程中保持了系統(tǒng)的可擴(kuò)展性、高效性功氨。
- 對(duì)比三:架構(gòu)
- 傳統(tǒng)技術(shù)中序苏,一般大都為二層的系統(tǒng)架構(gòu),即Web服務(wù)器+數(shù)據(jù)庫(kù)服務(wù)器捷凄,導(dǎo)致網(wǎng)站訪問(wèn)量大的時(shí)候忱详,無(wú)法克服CGI程序與數(shù)據(jù)庫(kù)建立連接時(shí)速度慢的瓶頸,從而死機(jī)跺涤、數(shù)據(jù)庫(kù)死鎖現(xiàn)象頻繁發(fā)生匈睁。
- Servlet有連接池的概念,它可以利用多線程的優(yōu)點(diǎn)桶错,在系統(tǒng)緩存中事先建立好若干與數(shù)據(jù)庫(kù)的連接航唆,到時(shí)候若想和數(shù)據(jù)庫(kù)打交道可以隨時(shí)跟系統(tǒng)"要"一個(gè)連接即可,反應(yīng)速度可想而知院刁。
- 對(duì)比一:性能
Servlet的生命周期
- 加載:容器通過(guò)類(lèi)加載器使用Servlet類(lèi)對(duì)應(yīng)的文件來(lái)加載Servlet
- 創(chuàng)建:通過(guò)調(diào)用Servlet的構(gòu)造函數(shù)來(lái)創(chuàng)建一個(gè)Servlet實(shí)例
- 初始化:通過(guò)調(diào)用Servlet的init()方法來(lái)完成初始化工作糯钙,這個(gè)方法是在Servlet已經(jīng)被創(chuàng)建,但在向客戶端提供服務(wù)之前調(diào)用。
- 處理客戶請(qǐng)求:Servlet創(chuàng)建后就可以處理請(qǐng)求任岸,當(dāng)有新的客戶端請(qǐng)求時(shí)再榄,Web容器都會(huì)創(chuàng)建一個(gè)新的線程來(lái)處理該請(qǐng)求。接著調(diào)用Servlet的Service()方法來(lái)響應(yīng)客戶端請(qǐng)求(Service方法會(huì)根據(jù)請(qǐng)求的method屬性來(lái)調(diào)用doGet()和doPost())
- 卸載:容器在卸載Servlet之前需要調(diào)用destroy()方法享潜,讓Servlet釋放其占用的資源困鸥。
Struts1和Struts2的區(qū)別和對(duì)比:
-
Action 類(lèi):
- Struts1要求Action類(lèi)繼承一個(gè)抽象基類(lèi)。Struts1的一個(gè)普遍問(wèn)題是使用抽象類(lèi)編程而不是接口米碰,而struts2的Action是接口窝革。
- Struts 2 Action類(lèi)可以實(shí)現(xiàn)一個(gè)Action接口,也可實(shí)現(xiàn)其他接口吕座,使可選和定制的服務(wù)成為可能虐译。Struts2提供一個(gè)ActionSupport基類(lèi)去 實(shí)現(xiàn) 常用的接口。Action接口不是必須的吴趴,任何有execute標(biāo)識(shí)的POJO對(duì)象都可以用作Struts2的Action對(duì)象漆诽。
-
線程模式:
- Struts1 Action是單例模式并且必須是線程安全的,因?yàn)閮H有Action的一個(gè)實(shí)例來(lái)處理所有的請(qǐng)求锣枝。單例策略限制了Struts1 Action能作的事厢拭,并且要在開(kāi)發(fā)時(shí)特別小心。Action資源必須是線程安全的或同步的撇叁。
- Struts2 Action對(duì)象為每一個(gè)請(qǐng)求產(chǎn)生一個(gè)實(shí)例供鸠,因此沒(méi)有線程安全問(wèn)題。(實(shí)際上陨闹,servlet容器給每個(gè)請(qǐng)求產(chǎn)生許多可丟棄的對(duì)象楞捂,并且不會(huì)導(dǎo)致性能和垃圾回收問(wèn)題)
-
Servlet 依賴(lài):
- Struts1 Action 依賴(lài)于Servlet API ,因?yàn)楫?dāng)一個(gè)Action被調(diào)用時(shí)HttpServletRequest 和 HttpServletResponse 被傳遞給execute方法。
- Struts 2 Action不依賴(lài)于容器趋厉,允許Action脫離容器單獨(dú)被測(cè)試寨闹。如果需要,Struts2 Action仍然可以訪問(wèn)初始的request和response君账。但是繁堡,其他的元素減少或者消除了直接訪問(wèn)HttpServetRequest 和 HttpServletResponse的必要性。
-
可測(cè)性:
- 測(cè)試Struts1 Action的一個(gè)主要問(wèn)題是execute方法暴露了servlet API(這使得測(cè)試要依賴(lài)于容器)乡数。一個(gè)第三方擴(kuò)展--Struts TestCase--提供了一套Struts1的模擬對(duì)象(來(lái)進(jìn)行測(cè)試)椭蹄。
- Struts 2 Action可以通過(guò)初始化、設(shè)置屬性净赴、調(diào)用方法來(lái)測(cè)試塑娇,“依賴(lài)注入”支持也使測(cè)試更容易。
-
捕獲輸入:
- Struts1 使用ActionForm對(duì)象捕獲輸入劫侧。所有的ActionForm必須繼承一個(gè)基類(lèi)。因?yàn)槠渌鸍avaBean不能用作ActionForm,開(kāi)發(fā)者經(jīng)常創(chuàng)建多余的類(lèi)捕獲輸入烧栋。動(dòng)態(tài)Bean(DynaBeans)可以作為創(chuàng)建傳統(tǒng)ActionForm的選擇写妥,但是,開(kāi)發(fā)者可能是在重新描述(創(chuàng)建)已經(jīng)存 在的JavaBean(仍然會(huì)導(dǎo)致有冗余的javabean)审姓。
- Struts 2直接使用Action屬性作為輸入屬性珍特,消除了對(duì)第二個(gè)輸入對(duì)象的需求。輸入屬性可能是有自己(子)屬性的rich對(duì)象類(lèi)型魔吐。Action屬性能夠通過(guò) web頁(yè)面上的taglibs訪問(wèn)扎筒。Struts2也支持ActionForm模式。rich對(duì)象類(lèi)型酬姆,包括業(yè)務(wù)對(duì)象嗜桌,能夠用作輸入/輸出對(duì)象。這種 ModelDriven 特性簡(jiǎn)化了taglib對(duì)POJO輸入對(duì)象的引用辞色。
-
表達(dá)式語(yǔ)言:
- Struts1 整合了JSTL骨宠,因此使用JSTL EL。這種EL有基本對(duì)象圖遍歷相满,但是對(duì)集合和索引屬性的支持很弱层亿。
- Struts2可以使用JSTL,但是也支持一個(gè)更強(qiáng)大和靈活的表達(dá)式語(yǔ)言--"Object Graph Notation Language" (OGNL).
AWT & Swing
AWT :是通過(guò)調(diào)用操作系統(tǒng)的native方法實(shí)現(xiàn)的立美,所以在Windows系統(tǒng)上的AWT窗口就是Windows的風(fēng)格匿又,而在Unix系統(tǒng)上的則是XWindow風(fēng)格。 AWT 中的圖形函數(shù)與 操作系統(tǒng) 所提供的圖形函數(shù)之間有著一一對(duì)應(yīng)的關(guān)系建蹄,我們把它稱(chēng)為peers碌更。 也就是說(shuō),當(dāng)我們利用 AWT 來(lái)構(gòu)件圖形用戶界面的時(shí)候躲撰,我們實(shí)際上是在利用 操作系統(tǒng) 所提供的圖形庫(kù)针贬。由于不同 操作系統(tǒng) 的圖形庫(kù)所提供的功能是不一樣的,在一個(gè)平臺(tái)上存在的功能在另外一個(gè)平臺(tái)上則可能不存在拢蛋。為了實(shí)現(xiàn)Java語(yǔ)言所宣稱(chēng)的"一次編譯桦他,到處運(yùn)行"的概念,AWT 不得不通過(guò)犧牲功能來(lái)實(shí)現(xiàn)其平臺(tái)無(wú)關(guān)性谆棱,也就是說(shuō)快压,AWT 所提供的圖形功能是各種通用型操作系統(tǒng)所提供的圖形功能的交集。由于AWT 是依靠本地方法來(lái)實(shí)現(xiàn)其功能的垃瞧,我們通常把AWT控件稱(chēng)為重量級(jí)控件蔫劣。
Swing :是所謂的Lightweight組件,不是通過(guò)native方法來(lái)實(shí)現(xiàn)的个从,所以Swing的窗口風(fēng)格更多樣化脉幢。但是,Swing里面也有heaveyweight組件歪沃。比如JWindow,Dialog,JFrame嫌松;Swing由純Java寫(xiě)成沪曙,可移植性好,外觀在不同平臺(tái)上相同萎羔。所以Swing部件稱(chēng)為輕量級(jí)組件( Swing是由純JAVA CODE所寫(xiě)的液走,因此SWING解決了JAVA因窗口類(lèi)而無(wú)法跨平臺(tái)的問(wèn)題,使窗口功能也具有跨平臺(tái)與延展性的特性贾陷,而且SWING不需占有太多系統(tǒng)資源缘眶,因此稱(chēng)為輕量級(jí)組件!K璺稀O镄浮)
Struts工作原理
- MVC即Model-View-Controller的縮寫(xiě),是一種常用的設(shè)計(jì)模式瓦哎。MVC減弱了業(yè)務(wù)邏輯接口和數(shù)據(jù)接口之間的耦合砸喻,以及讓視圖層更富于變化。
- Struts是MVC的一種實(shí)現(xiàn)蒋譬,它將Servlet和JSP標(biāo)記(屬于J2EE規(guī)范)用作實(shí)現(xiàn)的一部分割岛。Struts繼承了MVC的各項(xiàng)特性,并根據(jù)J2EE的特點(diǎn)犯助,做了相應(yīng)的變化與擴(kuò)展癣漆。
- 控制器:有一個(gè)XML文件struts-config.xml,與之相關(guān)聯(lián)的是Controller剂买,在Struts中惠爽,承擔(dān)MVC中Controller角 色的是一個(gè)Servlet,叫ActionServlet瞬哼。ActionServlet是一個(gè)通用的控制組件婚肆。這個(gè)控制組件提供了處理所有發(fā)送到 Struts的HTTP請(qǐng)求的入口點(diǎn)。它截取和分發(fā)這些請(qǐng)求到相應(yīng)的動(dòng)作類(lèi)(這些動(dòng)作類(lèi)都是Action類(lèi)的子類(lèi))坐慰。另外控制組件也負(fù)責(zé)用相應(yīng)的請(qǐng)求參數(shù)填充Action From(通常稱(chēng)之為FromBean),并傳給動(dòng)作類(lèi)(通常稱(chēng)之為ActionBean)较性。動(dòng)作類(lèi)實(shí)現(xiàn)核心商業(yè)邏輯,它可以訪問(wèn)java bean 或調(diào)用EJB结胀。最后動(dòng)作類(lèi)把控制權(quán)傳給后續(xù)的JSP文件赞咙,后者生成視圖。所有這些控制邏輯利用struts-config.xml文件來(lái)配置糟港。
- 視圖:主要由JSP生成頁(yè)面完成視圖攀操,Struts提供豐富的JSP 標(biāo)簽庫(kù): Html,Bean秸抚,Logic,Template等,這有利于分開(kāi)表現(xiàn)邏輯和程序邏輯嬉探。
- 模型:模型以一個(gè)或多個(gè)java bean的形式存在。這些bean分為三類(lèi):Action Form县钥、Action、JavaBean or EJB慈迈。Action Form通常稱(chēng)之為FormBean,封裝了來(lái)自于Client的用戶請(qǐng)求信息省有,如表單信息痒留。Action通常稱(chēng)之為ActionBean,獲取從 ActionSevlet傳來(lái)的FormBean蠢沿,取出FormBean中的相關(guān)信息伸头,并做出相關(guān)的處理,一般是調(diào)用Java Bean或EJB等舷蟀。
- 流程:在Struts中恤磷,用戶的請(qǐng)求一般以.do作為請(qǐng)求服務(wù)名,所有的.do請(qǐng)求均被指向 ActionSevlet野宜,ActionSevlet根據(jù)Struts-config.xml中的配置信息扫步,將用戶請(qǐng)求封裝成一個(gè)指定名稱(chēng)的 FormBean,并將此FormBean傳至指定名稱(chēng)的ActionBean匈子,由ActionBean完成相應(yīng)的業(yè)務(wù)操作河胎,如文件操作,數(shù)據(jù)庫(kù)操作等虎敦。 每一個(gè)*.do均有對(duì)應(yīng)的FormBean名稱(chēng)和ActionBean名稱(chēng)游岳,這些在Struts-config.xml中配置。
-
核心:Struts的核心是ActionSevlet其徙,ActionSevlet的核心是Struts-config.xml胚迫。
JSP文件的動(dòng)靜包含
動(dòng)態(tài) INCLUDE 用 jsp:include 動(dòng)作實(shí)現(xiàn) <jsp:include page="included.jsp" flush="true" /> 它總是會(huì)檢查所含文件中的變化 , 適合用于包含動(dòng)態(tài)頁(yè)面 , 并且可以帶參數(shù)。各個(gè)文件分別先編譯唾那,然后組合成一個(gè)文件访锻。
靜態(tài) INCLUDE 用 include 偽碼實(shí)現(xiàn) , 定不會(huì)檢查所含文件的變化 , 適用于包含靜態(tài)頁(yè)面 <%@ include file="included.htm" %> 。先將文件的代碼被原封不動(dòng)地加入到了主頁(yè)面從而合成一個(gè)文件通贞,然后再進(jìn)行翻譯朗若,此時(shí)不允許有相同的變量。
-
以下是對(duì) include 兩種用法的區(qū)別 昌罩, 主要有兩個(gè)方面的不同 ;
- 執(zhí)行時(shí)間上 :
<%@ include file="relativeURI"%> 是在翻譯階段執(zhí)行
<jsp:include page="relativeURI" flush="true" /> 在請(qǐng)求處理階段執(zhí)行 . - 引入內(nèi)容的不同 :
<%@ include file="relativeURI"%>
引入靜態(tài)文本 (html,jsp), 在 JSP 頁(yè)面被轉(zhuǎn)化成 servlet 之前和它融和到一起 .
<jsp:include page="relativeURI" flush="true" /> 引入執(zhí)行頁(yè)面或 servlet 所生成的應(yīng)答文本 .
- 執(zhí)行時(shí)間上 :
常見(jiàn)JVM配置參數(shù)釋義
常見(jiàn)配置匯總
- 堆設(shè)置
- -Xms:初始堆大小
- -Xmx:最大堆大小
- -XX:NewSize=n:設(shè)置年輕代大小
- -XX:NewRatio=n:設(shè)置年輕代和年老代的比值哭懈。如:為3,表示年輕代與年老代比值為1:3茎用,年輕代占整個(gè)年輕代年老代和的1/4
- -XX:SurvivorRatio=n:年輕代中Eden區(qū)與兩個(gè)Survivor區(qū)的比值遣总。注意Survivor區(qū)有兩個(gè)睬罗。如:3,表示Eden:Survivor=3:2旭斥,一個(gè)Survivor區(qū)占整個(gè)年輕代的1/5
- -XX:MaxPermSize=n:設(shè)置持久代大小
- 收集器設(shè)置
- -XX:+UseSerialGC:設(shè)置串行收集器
- -XX:+UseParallelGC:設(shè)置并行收集器
- -XX:+UseParalledlOldGC:設(shè)置并行年老代收集器
- -XX:+UseConcMarkSweepGC:設(shè)置并發(fā)收集器
- 垃圾回收統(tǒng)計(jì)信息
- -XX:+PrintGC
- -XX:+PrintGCDetails
- -XX:+PrintGCTimeStamps
- -Xloggc:filename
- 并行收集器設(shè)置
- -XX:ParallelGCThreads=n:設(shè)置并行收集器收集時(shí)使用的CPU數(shù)容达。并行收集線程數(shù)。
- -XX:MaxGCPauseMillis=n:設(shè)置并行收集最大暫停時(shí)間
- -XX:GCTimeRatio=n:設(shè)置垃圾回收時(shí)間占程序運(yùn)行時(shí)間的百分比垂券。公式為1/(1+n)
- 并發(fā)收集器設(shè)置
- -XX:+CMSIncrementalMode:設(shè)置為增量模式花盐。適用于單CPU情況。
- -XX:ParallelGCThreads=n:設(shè)置并發(fā)收集器年輕代收集方式為并行收集時(shí)菇爪,使用的CPU數(shù)算芯。并行收集線程數(shù)。
-Xms -Xmx分別設(shè)置堆的最小值和最大值凳宙,如果要設(shè)置成堆的大小可變熙揍,那么可以將最大值和最小值設(shè)置成不一樣,如果要將堆大小固定氏涩,那么只需將最大值和最小值設(shè)置成一樣的就行届囚。
jvm中分為堆和方法區(qū)
https://www.nowcoder.com/questionTerminal/970cdaaa4a114cbf9fef82213a7dabca
堆又進(jìn)一步分為新生代和老年代
方法區(qū)為永久代
堆中區(qū)分的新生代和老年代是為了垃圾回收,新生代中的對(duì)象存活期一般不長(zhǎng)是尖,而老年代中的對(duì)象存活期較長(zhǎng)意系,所以當(dāng)垃圾回收器回收內(nèi)存時(shí),新生代中垃圾回收效果較好析砸,會(huì)回收大量的內(nèi)存昔字,而老年代中回收效果較差,內(nèi)存回收不會(huì)太多首繁。
基于以上特性作郭,新生代中一般采用復(fù)制算法,因?yàn)榇婊钕聛?lái)的對(duì)象是少數(shù)弦疮,所需要復(fù)制的對(duì)象少夹攒,而老年代對(duì)象存活多,不適合采用復(fù)制算法胁塞,一般是標(biāo)記整理和標(biāo)記清除算法咏尝。
因?yàn)閺?fù)制算法需要留出一塊單獨(dú)的內(nèi)存空間來(lái)以備垃圾回收時(shí)復(fù)制對(duì)象使用,所以將新生代分為eden區(qū)和兩個(gè)survivor區(qū)啸罢,每次使用eden和一個(gè)survivor區(qū)编检,另一個(gè)survivor作為備用的對(duì)象復(fù)制內(nèi)存區(qū)。
綜上:
-Xmn設(shè)置了新生代的大小為5120m扰才,而-XXSurvivorRatio=3允懂,所有將新生代共分成5分,eden占三份衩匣,survivor占兩份蕾总,每份1/5
算法問(wèn)題:# 二叉樹(shù)中任意兩個(gè)節(jié)點(diǎn)的最近公共祖先
思路:從根節(jié)點(diǎn)開(kāi)始遍歷粥航,如果node1和node2中的任一個(gè)和root匹配,那么root就是最低公共祖先生百。 如果都不匹配递雀,則分別遞歸左、右子樹(shù)蚀浆,如果有一個(gè) 節(jié)點(diǎn)出現(xiàn)在左子樹(shù)缀程,并且另一個(gè)節(jié)點(diǎn)出現(xiàn)在右子樹(shù),則root就是最低公共祖先. 如果兩個(gè)節(jié)點(diǎn)都出現(xiàn)在左子樹(shù)市俊,則說(shuō)明最低公共祖先在左子樹(shù)中杠输,否則在右子樹(shù)。
代碼實(shí)現(xiàn)
public class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//發(fā)現(xiàn)目標(biāo)節(jié)點(diǎn)則通過(guò)返回值標(biāo)記該子樹(shù)發(fā)現(xiàn)了某個(gè)目標(biāo)結(jié)點(diǎn)
if(root == null || root == p || root == q) return root;
//查看左子樹(shù)中是否有目標(biāo)結(jié)點(diǎn)秕衙,沒(méi)有為null
TreeNode left = lowestCommonAncestor(root.left, p, q);
//查看右子樹(shù)是否有目標(biāo)節(jié)點(diǎn),沒(méi)有為null
TreeNode right = lowestCommonAncestor(root.right, p, q);
//都不為空僵刮,說(shuō)明做右子樹(shù)都有目標(biāo)結(jié)點(diǎn)据忘,則公共祖先就是本身
if(left!=null&&right!=null) return root;
//如果發(fā)現(xiàn)了目標(biāo)節(jié)點(diǎn),則繼續(xù)向上標(biāo)記為該目標(biāo)節(jié)點(diǎn)
return left == null ? right : left;
}
}