【7萬字乾貨】2021Java實習必看面試兩百題解析
①自己想總結一篇同時包含質與量的文章,給自己,也給關注我的人。
②最近在投遞實習,所以主要都是Java的基礎知識,計算機網路和作業系統就只挑重點,本文後面視情況會繼續更新。以後可能會完善包括資料結構和演算法、場景題、Linux之類的內容。
③所有題目及答案全部手打,轉載註明出處。
④如有有錯誤歡迎指出。
⑤如果不喜歡直接關掉,別吐槽。
JavaSE 88
基礎語法 9
Q1:簡單說說Java有哪些資料型別
答:①分為基本資料型別和引用資料型別。②基本資料型別包括:數值型(byte、short、int、long、float、double),字元型(char)以及布林型(boolean)。除了基本型別外,其他資料型別都屬於引用型別,包括類、介面、陣列等。
Q2:float number=3.4;
有沒有問題?為什麼?
答:有問題,因為3.4 是雙精度數,將雙精度型(double)賦值給浮點型(float)屬於向下轉型,可能會造成精度損失,所以必須進行強制型別轉換,正確的寫法是float number =(float)3.4;
/ float number =3.4F;
。
Q3:字串拼接的方式以及效率?
答:①使用+
直接拼接,String 是final物件,不會被修改,每次使用 +
進行拼接都會建立新的物件,而不是改變原來的物件,效率低,是執行緒安全的。②使用StringBuffer可變字串,效率較高,是執行緒安全的(StringBuffer的方法使用了synchronized
關鍵字進行修飾)。③使用StringBuilder可變字串,效率最高,但是執行緒不安全。
Q4:簡述final,finally和finalize區別
答:①final可以修飾類,方法和變數,被final修飾的類不可繼承,被final修飾的方法不可重寫,被final修飾的變數引用不可更改,引用的內容可以更改。②finally用於try-catch程式碼塊中,無論是否發生異常最後都將執行,作用是釋放資源。③finalize是Object類的方法,在物件被垃圾回收之前將呼叫一次,一般用於資源的釋放。
Q5:==和equals有什麼區別?equals和hashCode有什麼聯絡?
答:①如果是引用型別,==
比較的是兩個物件的引用是否完全相同,如果是基本型別,比較的是兩個基本型別的數值是否相同。②如果沒有重寫的話,equals預設按照==
進行比較,如果重寫了equals()方法,則按照對應的比較規則比較。③兩個物件如果相等,那麼它們的hashCode值必須相等,但兩個物件的hashCode值相等時,它們不一定相同。
Q6:Array和ArrayList的區別?
答:①Array長度在定義之後就不執行改變了,而ArrayList是長度可變的,可以自動擴容。②Array只能儲存相同型別的資料,ArrayList可以儲存不同型別的資料。③ArrayList提供了更多運算元據的方法。
Q7:&和&&的區別?
答:①&具有按位與和邏輯與兩個功能。②&&作為邏輯與具有短路的特點,當前面的條件表示式為false時就不會進行後面條件表示式的判斷,可以用來避免空指標異常。
Q8:簡述JDK8的新特性
答:①介面中可以新增default
修飾的非抽象方法,可以有方法體和內容。②可以使用lambda表示式,減少程式碼冗餘。③函式式介面,使用@FunctionalInterface
註解標明,該介面有且僅有一個抽象方法。④方法引用,可以直接引用已有Java類或物件的方法或構造器,進一步簡化lambda表示式。⑤stream流,用於解決已有集合/陣列類庫的弊端,簡化其操作,有foreach
遍歷、filter
過濾、map
對映、concat
合併等功能。⑥增加日期相關的API。
Q9:Stream流了解嗎?
答:①Stream流是JDK1.8的新特性,用於解決已有集合/陣列類庫的弊端,簡化集合/陣列的操作。②stream流的獲取:集合:直接呼叫stream()方法獲取;陣列:使用靜態方法Stream.of()
/Arrays.stream()
獲取。③常用方法:forEach()
遍歷;count()
統計個數;filter()
按條件過濾;limit()
取前面n個元素;skip()
跳過前面n個元素;map()
對映加工;concat()
合併stream流。④終結方法:foreach/count 呼叫終結方法後流不能繼續使用;非終結方法:每次呼叫完返回一個新的stream物件,可以繼續使用,支援鏈式程式設計。⑤收集stream流:把流轉為Set集合 collect(Collections.toSet())
;把流轉為List集合 collect(Collections.toList())
;把流轉為Collection集合 collect(Collections.toCollection())
;把流轉為陣列 toArray()
。
物件導向 10
Q1:簡述物件導向的特性
答:①封裝:建議成員變數私有,然後提供公有的getter/setter方法來獲取值/賦值,封裝的核心思想是合理隱藏,合理暴露,可以提高安全性,實現程式碼的元件化。②繼承:一種子類到父類的關係,是“is a”關係,可以提高程式碼的複用性,相同程式碼可寫到父類,子類的功能更加強大,不僅得到了父類的功能,還有自己的功能。③多型:同一個型別的物件執行相同的行為,在不同的狀態下表現出不同的特徵。多型可以降低類之間的耦合度,右邊物件可以實現元件化切換,業務功能隨之改變,便於擴充套件和維護。
Q2:類和物件有什麼區別?
答:類是一個抽象的概念,是具有相同特徵的事物的描述,是物件的模板。物件是一個個具體的存在,是類的例項。
Q3:列舉Object類的方法
答:①equals(Object obj):判斷其他物件是否與當前物件相等。②toString():列印當前物件的字串表示。③wait():導致當前執行緒等待,等待其他執行緒喚醒,會釋放鎖。④notify()/notifyAll():隨機喚醒一個/全部執行緒。⑤hashCode():返回當前物件的hashCode值。⑥finalize():當垃圾回收器要回收物件前呼叫。⑦clone():建立並返回物件的一個副本。
Q4:方法過載和方法重寫的區別?
答:①方法過載是同一個類中具有不同引數列表的同名方法(無關返回值型別),方法重寫是子類中具有和父類相同引數列表的同名方法,會覆蓋父類原有的方法。②過載的返回值型別和許可權修飾符,異常丟擲型別沒有要求,重寫方法的返回值型別小於等於父類被重寫方法的返回值型別,修飾符許可權大於等於父類被重寫方法許可權修飾符,丟擲的異常型別小於等於父類被重寫方法丟擲的異常型別。
Q5:介面和抽象類有什麼區別?
答:①介面中只能定義public staic final修飾的常量,抽象類中可以定義普通變數。②介面和抽象類都不能例項化,但介面沒有構造器,抽象類有構造器。③介面可以多實現,抽象類只能單繼承。④介面在JDK1.8之前只能定義public abstract修飾的方法,JDK1.8開始可以定義預設方法和靜態方法,JDK1.9開始可以定義私有方法,抽象類中的方法沒有限制。
Q6:什麼時候應該使用介面,什麼時候應該使用抽象類?
答:①如果知道某個類應該成為基類,那麼第一選擇應該是讓它成為一個介面,只有在必須要有方法定義和成員變數的時候,才應該選擇抽象類。②在介面和抽象類的選擇上,必須遵守這樣一個原則:行為模型應該總是通過介面而不是抽象類定義。通過抽象類建立行為模型會出現的問題:如果有一個抽象類Moblie,有兩個繼承它的類Mobile1和Moblie2,分別有自己的功能1和功能2,如果出現一個既有功能1又有功能2的新產品需求,由於Java不允許多繼承就出現了問題,而如果是介面的話只需要同時實現兩個介面即可。
Q7:內部類有什麼作用?有哪些分類?
答:①內部類有更好的封裝性,有更多的許可權修飾符,封裝性可以得到更多的控制。②靜態內部類:由static修飾,屬於類本身,只載入一次。類可以定義的成分靜態內部類都可以定義,可以訪問外部類的靜態變數和方法,通過new 外部類.靜態內部類構造器
來建立物件。③成員內部類:屬於外部類的每個物件,隨物件一起載入。不可以定義靜態成員和方法,可以訪問外部類的所有內容,通過new 外部類構造器.new 成員內部類構造器
來建立物件。④區域性內部類:定義在方法、構造器、程式碼塊、迴圈中。只能定義例項成員變數和例項方法,作用範圍僅在區域性程式碼塊中。⑤匿名內部類:沒有名字的區域性內部類,可以簡化程式碼,匿名內部類會立即建立一個匿名內部類的物件返回,物件型別相當於當前new的類的子類型別。
Q8:泛型和泛型擦除是什麼?
答:①泛型的本質是引數化型別,泛型提供了編譯時型別的安全檢測機制,該機制允許程式在編譯時檢測非法的型別。②在編譯階段採用泛型時加上的型別引數,會被編譯器在編譯時去掉,這個過程就被稱為型別擦除,因此泛型主要用於編譯階段,在編譯後生成的Java位元組程式碼檔案中不包含泛型中的型別資訊。
Q9:泛型標記的規範瞭解嗎?
答:①E
:值Element,在集合中使用,表示在集合中存放的元素。②T
:指Type,表示Java類,包括基本的類以及自定義類。③K
:指Key,表示鍵,例如Map集合中的Key。④V
:指Value,表示值,例如Map集合中的Value。⑤N
:指Number,表示數值型別。⑥?
:表示不確定的Java型別。
Q10:泛型限定是什麼?
答:①型別萬用字元使用?表示所有具體的引數型別,在使用泛型的時候,如果希望將類的繼承關係加入泛型應用中就需要對泛型做限定,具體的泛型限定有對泛型上限的限定以及對泛型下限的限定。②對泛型上限的限定使用<? extends T>,它表示該萬用字元所代表的型別是T類的子型別或T介面的子介面。③對泛型下限的限定使用<? super T>,它表示該萬用字元所代表的型別是T類的父型別或T介面的父介面。
異常 2
Q1:異常有哪些分類?出現的原因是什麼?
答:①Throwable是所有錯誤和異常的父類,Throwable分為Error和Exception。②Error指Java程式執行錯誤,出現Error通常是因為系統的內部錯誤或資源耗盡,Error不能在執行過程中被動態處理,如果程式執行中出現Error,系統只能記錄錯誤的原因和安全終止。③Exception指Java程式執行異常,即執行中發生了不期望的情況,分為RuntimeException和CheckedException。RuntimeException指在Java虛擬機器正常執行期間丟擲的異常,可以被捕獲並處理,例如空指標異常,陣列越界等。CheckedException指編譯階段強制要求捕獲並處理的異常,例如IO異常,SQL異常等。
Q2:有哪些異常處理方式?
答:①丟擲異常:遇到異常不進行具體處理,而是將異常丟擲給呼叫者,由呼叫者根據情況處理。丟擲異常有2種形式,一種是throws,作用在方法上,一種是throw,作用在方法內。②使用try/catch進行異常的捕獲處理,try中發生的異常會被catch程式碼塊捕獲,根據情況進行處理,如果有finally程式碼塊無論是否發生異常都會執行,一般用於釋放資源,JDK1.7開始可以將資源定義在try程式碼塊中自動釋放減少程式碼。
集合 10
Q1:簡述一下集合主要有哪些類和介面,各自有什麼特點
答:①主要有兩個介面Collection和Map,其中Collection又包括List、Set和Queue。②List是有序的,主要包括ArrayList,LinkedList和Vector,ArrayList底層通過陣列實現,執行緒不安全,Vector是執行緒安全的ArrayList,但效率較低,LinkedList底層通過雙向連結串列實現,與ArrayList相比增刪快查詢慢。③Set是唯一且無序的,主要包括HashSet,LinkedHashSet和TreeSet。HashSet底層其實就是HashMap,利用了key來保證元素的唯一性。LinkedHashSet可以按照key的操作順序排序,TreeSet支援按照預設或指定的排序規則排序。④Queue是佇列結構,主要有ArrayBlockingQueue基於陣列的阻塞佇列、LinkedBlockingQueue基於連結串列的阻塞佇列等。⑤Map以key-value鍵值對的形式儲存元素,主要包括HashMap、LinkedHashMap和TreeMap。HashMap底層通過陣列+連結串列/紅黑樹實現,LinkedHashMap可以按照key的操作順序對集合排序,TreeMap可以按照預設或指定的排序規則對集合排序。
Q2:HashMap是執行緒安全的嗎?
答:①HashMap是執行緒不安全的,可以使用ConcurrentHashMap保證執行緒安全。②ConcurrentHashMap基於減小鎖粒度的思想,通過使用分段鎖來實現執行緒安全,內部細分為很多Segment資料段,預設情況下為16個,對每個Segment的資料都單獨進行加鎖操作,Segment的個數為鎖的併發度。ConcurrentHashMap是由Segment陣列和HashEntry陣列組成的,Segment繼承了可重入鎖,HashEntry用來儲存鍵值對資料。③Segment的結構和HashMap類似,是陣列和連結串列結構,每個Segment裡面都包含一個HashEntry陣列,每個HashEntry都是一個連結串列結構的資料要對其進行i修改必須先獲得對應的Segment鎖。④多執行緒下只要加入的資料hashCode對映的資料段不一樣就可以做到並行的執行緒安全。
Q3:List、Set、Map有什麼區別?
答:①List是有序、可重複、有索引的集合,繼承了Collection集合全部功能 除了Collection的三種遍歷方式外,可用索引遍歷。②Set是無序,不可重複的集合,Set的實現類LinkedHashSet和TreeSet是有序的,LinkedHashSet可以按照元素插入的順序排序,也可以按照元素操作的時間排序,TreeSet可以按照預設的比較規則或者自定義的比較規則排序。③Map是無序、以key-value的鍵值對形式儲存元素的集合,鍵不可重複,值無要求,重複的鍵對應的值會覆蓋之前的值。
Q4:HashSet是如何去重的?
答:①對於基本型別的包裝類,可以直接按值進行比較。②對於引用資料型別,會先比較hashCode()返回值是否相同,如果不同則代表不是同一個物件,如果相同則繼續比較equals()方法返回值是否相同,都相同說明是同一個物件。③如果希望內容相同的物件就代表物件相同,那麼除了重寫equals()方法還要重寫hashCode()方法,因為內容相同的物件hashCode()值不一定相同,因為只有hashCode()和equals()都相同才說明是同一個物件。
Q5:HashMap和HashSet的底層是怎麼實現的?
答:①JDK1.8之前,HashMap的底層是陣列加連結串列實現。陣列中的每個元素都是一個單連結串列,連結串列中的每個元素都是Entry的實現類Node的一個例項,Node包括4個屬性:key、value、hash值和用於指向單連結串列下一個元素的next。②HashMap在查詢資料時,根據hash值可以快速定位到陣列的具體下標,然後對連結串列進行遍歷查詢資料的時間複雜度為O(n)。JDK1.8起對HashMap進行了優化,底層改為陣列+連結串列或紅黑樹,當連結串列中的元素超過8個之後,HashMap會將連結串列結構轉換未紅黑樹以提高查詢效率,時間複雜度為O(logn)。②HashSet的底層是基於HashMap實現的,HashSet中的元素只是存放在了底層HashMap的key上, 而value使用一個static final的Object物件標識。因此HashSet 的實現比較簡單,相關操作基本上都是直接呼叫底層HashMap的相關方法來完成的。
Q6:Collection和Collections有什麼區別?
答:①Collection是一個集合介面,它包括List有序集合、Set無序集合、Queue佇列等。②Collections則是Collection的一個工具類,為Collection型別的物件提供了很多方便的方法,例如addAll可以直接對Collection集合批量新增元素,shuffle可以隨機打亂List集合的元素順序,sort可以對List集合進行預設或按比較器進行排序。
Q7:迭代器是什麼?
答:①迭代器實現了Iterator介面,是用於遍歷Collection集合元素的一個指標。②主要有三個方法:通過iterator()獲得集合的迭代器;通過hasNext()判斷集合當中是否還有元素,如果有返回true,沒有則返回false,初始時迭代器位於第一個元素之前;通過next()獲取集合的下一個元素,並向後移動一個元素的單位。
Q8:在使用foreach迴圈遍歷集合元素時能否新增或刪除元素?
答:使用foreach迴圈遍歷元素集合時不能修改或刪除元素,通過java -c檢視位元組碼可以發現foreach迴圈實際上是用Iterator迭代器實現的,如果進行新增或刪除元素會丟擲ConcurrentModificationException異常,因為新增或刪除元素會改變modCount的值,modCount是集合類的一個成員變數,代表集合的修改次數,當modCount的值和預期的exceptedModCount值不一致時就會丟擲ConcurrentModificationException異常。
Q9:Queue介面中的add()/offer()、remove()/poll()、element()/peek()方法有什麼區別?
答:①add()和offer()都是向佇列尾部插入一個元素,區別是當超出佇列界限時,add方法會丟擲異常,而offer()會返回false。②remove()和poll()都是從佇列頭部移除一個元素並返回,區別是佇列為空時remove()方法會丟擲異常,poll()方法則是返回null值。③element()和 peek() 都是用於查詢佇列頭部的元素,區別時佇列為空時, element() 丟擲一個異常,而 peek() 返回 null。
Q10:有哪些執行緒安全的集合類?
答:①Vector,是執行緒安全的ArrayList,底層用陣列實現,通過synchronized修飾方法保證執行緒安全。②HashTable,是執行緒安全的HashMap,繼承自Dictionary,通過synchronized修飾方法保證執行緒安全,效能較差。③ConcurentHashMap,執行緒安全的HashMap,通過分段鎖實現執行緒安全,效能較好。
多執行緒 34
Q1:建立執行緒有哪幾種實現方式?分別有什麼優缺點?
答:①繼承Thread類,重寫run()方法即可。優點是編碼簡單,缺點是不能繼承其他類,功能單一。②實現Runnable介面,重寫run()
方法,並將該實現類作為引數傳入Thread構造器。優點是可以繼承其他類,避免了單繼承的侷限性;適合多個相同程式程式碼的執行緒共享一個資源(同一個執行緒任務物件可被包裝成多個執行緒物件),實現解耦操作,程式碼和執行緒獨立。缺點是實現相對複雜。③實現Callable介面,重寫call()
方法,幷包裝成FutureTask物件,再作為引數傳入Thread構造器。優點是相比方式二可以獲取返回值,缺點是實現複雜。④可以通過執行緒池建立。
Q2:執行緒有哪些狀態?
答:①New:用new操作建立一個新執行緒,此時程式還未開始執行執行緒中的程式碼。②Runnable:呼叫start()方法後進入可執行狀態。③Blocked:阻塞狀態,內部鎖(不是juc中的鎖)獲取失敗時進入阻塞狀態。④Waiting:等待其他執行緒喚醒時進入等待狀態。⑤Timed Waiting:計時等待,帶超時引數的方法,例如sleep(long time)。⑥Terminated:終止狀態,執行緒正常執行完畢或被未捕獲異常終止。
Q3:什麼是執行緒安全問題,如何解決?
答:當多個執行緒對同一個共享變數進行操作時可能會產生的問題。解決方法:①使用內部鎖synchronized,可以使用同步程式碼塊,如果是例項方法可用this作為鎖物件,如果是靜態方法,可以用類.class作為鎖,或者使用同步方法底層和同步程式碼塊一樣,如果是例項方法預設用this作為鎖,如果是靜態方法預設使用類.class。②使用java.util.concurrent包中的鎖,例如ReentrantLock。
Q4:多執行緒不可見問題的原因和解決方式?
答:①不可見的原因是每個執行緒有自己的工作記憶體,執行緒都是從主記憶體拷貝共享變數的副本值。每個執行緒都是在自己的工作記憶體操作共享變數的。②解決方式:加鎖:獲得鎖後執行緒會清空工作記憶體,從主記憶體拷貝共享變數最新的值成為副本,修改後重新整理回主記憶體,再釋放鎖;使用volatile關鍵字:被volatile修飾的變數會通知其他執行緒之前讀取到的值已失效,執行緒會載入最新值到自己的工作記憶體。
Q5:說一說volatile關鍵字的作用
答:①保證被修飾的變數對所有執行緒可見,在一個執行緒修改了變數的值後,新的值對於其他執行緒是可以立即獲取的。②禁止指令重排序,被修飾的變數不會被快取在暫存器中或者對其他處理器不可見的地方,因此在讀取volatile修飾的變數時總是會返回最新寫入的值。③不會執行加鎖操作,不會導致執行緒阻塞,主要適用於一個變數被多個執行緒共享,多個執行緒均可對這個變數執行賦值或讀取的操作。④volatile可以嚴格保證變數的單次讀寫操作的原子性,但並不能保證像i++這種操作的原子性,因為i++在本質上是讀、寫兩次操作。
Q6:說一說synchronized關鍵字的作用
答:①用於為Java物件、方法、程式碼塊提供執行緒安全的操作,屬於排它的悲觀鎖,也屬於可重入鎖。②被synchronized修飾的方法和程式碼塊在同一時刻只能有一個執行緒訪問,其他執行緒只有等待當前執行緒釋放鎖資源後才能訪問。③Java中的每個物件都有一個monitor監視器物件,加鎖就是在競爭monitor,對程式碼塊加鎖是通過在前後分別加上monitorenter和monitorexit指令實現的,對方是否加鎖是通過一個標記位來判斷的。
Q7:synchronized的內部都包括哪些區域?
答:synchronized內部包括6個不同的區域,每個區域的資料都代表鎖的不同狀態。①ContentionList:鎖競爭佇列,所有請求鎖的執行緒都被放在競爭佇列中。②EntryList:競爭候選列表,在鎖競爭佇列中有資格成為候選者來競爭鎖資源的執行緒被移動到候選列表中。③WaitSet:等待集合,呼叫wait方法後阻塞的執行緒將被放在WaitSet。④OnDeck:競爭候選者,在同一時刻最多隻有一個執行緒在競爭鎖資源,該執行緒的狀態被稱為OnDeck。⑤Owner:競爭到鎖資源的執行緒狀態。⑥!Owner:釋放鎖後的狀態。
Q8:簡述synchronized的實現原理
答:①收到新的鎖請求時首先自旋,如果通過自旋也沒有獲取鎖資源,被放入ContentionList(該做法對於已經進入佇列的執行緒是不公平的,體現了synchronized的不公平性)。②為了防止ContentionList尾部的元素被大量執行緒進行CAS訪問影響效能,Owner執行緒會在是釋放鎖時將ContentionList的部分執行緒移動到EntryList並指定某個執行緒(一般是最先進入的)為OnDeck執行緒。Owner並沒有將鎖直接傳遞給OnDeck執行緒而是把鎖競爭的權利交給他,該行為叫做競爭切換,犧牲了公平性但提高了效能。③獲取到鎖的OnDeck執行緒會變為Owner執行緒,未獲取到的仍停留在EntryList中。④Owner執行緒在被wait阻塞後會進入WaitSet,直到某個時刻被喚醒再次進入EntryList。⑤ContentionList、EntryList、WaitSet中的執行緒均為阻塞狀態。⑥當Owner執行緒執行完畢後會釋放鎖資源並變為!Owner狀態。
Q9:JDK對synchronized做了哪些優化?
答:JDK1.6中引入了適應自旋、鎖消除、鎖粗化、輕量級鎖以及偏向鎖等以提高鎖的效率。鎖可以從偏向鎖升級到輕量級鎖,再升級到重量級鎖,這種過程叫做鎖膨脹。JDK1.6中預設開啟了偏向鎖和輕量級鎖,可以通過-XX:UseBiasedLocking
禁用偏向鎖。
Q10:volatile和synchronized的區別?
答:①volatile只能修飾例項變數和類變數,而synchronized可以修飾方法以及程式碼塊。②
volatile只能保證資料的可見性,但是不保證原子性,synchronized是一種排它機制,可以保證原子性。只有在特殊情況下才適合取代synchronized:對變數的寫操作不依賴於當前值(例如i++),或者是單純的變數賦值;該變數沒有被包含在具有其他變數的不等式中,不同的volatile變數不能互相依賴,只有在狀態真正獨立於程式內的其它內容時才能使用volatile。③volatile是一種輕量級的同步機制,在訪問volatile修飾的變數時並不會執行加鎖操作,執行緒不會阻塞,使用synchronized加鎖會阻塞執行緒。
Q11:講一講ReentrantLock
答:①ReentrantLock是Lock介面的實現類,是一個可重入式的獨佔鎖,通過AQS實現。②支援公平鎖與非公平鎖,還提供了可響應中斷鎖(執行緒在等待鎖的過程中可以根據需要取消對鎖的請求,通過interrupt方法中斷)、可輪詢鎖(通過tryLock獲取鎖,如果有可用鎖返回true否則立即返回false)、定時鎖(通過帶long時間引數的tryLock方法獲取鎖,如果在給定時間內獲取到可用鎖且當前執行緒未被中斷返回true,如果超過指定時間則返回false,如果獲取鎖時被終斷則丟擲異常並清除已終止狀態)等避免死鎖的方法。③通過lock和unlock方法顯式地加鎖和釋放鎖。
Q12:synchronized和ReentrantLock有哪些區別?
答:①synchronized是隱式鎖,ReentrantLock是顯式鎖,使用時必須在finally程式碼塊中進行釋放鎖的操作。②synchronized是非公平鎖,ReentrantLock可以實現公平鎖。③ReentrantLock可響應中斷,可輪迴,為處理鎖提高了更多靈活性。④synchronized是一個關鍵字,是JVM級別,ReentrantLock是一個介面,是API級別。⑤synchronized採用悲觀併發策略,ReentrantLock採用的是樂觀併發策略,會先嚐試以CAS方式獲取鎖。
Q13:Lock介面有哪些方法?
答:①lock()
:給物件加鎖。②tryLock()/tryLock(long time,TimeUnit unit)
:嘗試給物件加鎖,成功返回true,可以無參也可以指定等待時間。③unlock()
:釋放鎖,鎖只能由持有者釋放否則丟擲異常。④newCondition()
:建立條件物件,使用條件物件管理那些已經獲得鎖但不滿足有效條件的執行緒,呼叫await()方法把執行緒進入等待集,呼叫sign()/signAll()解除阻塞。⑤lockInterruptibly()
:如果當前執行緒未被中斷則獲取該鎖。
Q14:Java中的鎖有什麼作用?有哪些分類?
答:①Java中的鎖主要用於保障多併發情況下資料的一致性,執行緒必須先獲取鎖才能進行操作,可以保證資料的安全。②從樂觀和悲觀的角度可以分為樂觀鎖和悲觀鎖。③從獲取資源的公平性可以分為公平鎖和非公平鎖。④從是否共享資源的角度可以分為共享鎖和排它鎖。⑤從鎖的狀態角度可分為偏向鎖、輕量級鎖和重量級鎖。同時在JVM中還設計了自旋鎖以更快地使用CPU資源。
Q15:講一講樂觀鎖和悲觀鎖
答:①樂觀鎖採用樂觀的思想處理資料,在每次讀取資料時都認為別人不會修改該資料,所以不會上鎖。但在更新時會判斷在此期間別人有沒有更新該資料,通常採用在寫時先讀出當前版本號然後加鎖的方法,具體過程為:比較當前版本號與上一次的版本號,如果一致則更新,否則重複進行讀、比較、寫操作。Java中的樂觀鎖是基於CAS操作實現的,CAS是一種原子性操作,在對資料更新之前先比較當前值和傳入的值是否一樣,一樣則更新否則直接返回失敗狀態。②悲觀鎖採用悲觀的思想處理資料,每次讀取資料時都認為別人會修改資料,所以每次都會上鎖,其他執行緒將被阻塞。Java中的悲觀鎖基於AQS實現,該框架下的鎖會先嚐試以CAS樂觀鎖去獲取鎖,如果獲取不到則會轉為悲觀鎖。
Q16:講一講自旋鎖
答:①自旋鎖認為如果持有鎖的執行緒能在很短的時間內釋放鎖資源,那麼那些等待競爭鎖的執行緒就不需要做核心態和使用者態之間的切換進入阻塞、掛起狀態,只需等待小段時間,在等待持有鎖的執行緒釋放鎖後即可立即獲取鎖,這樣就避免了使用者執行緒在核心態的切換上導致鎖時間消耗。②優點:減少CPU的上下文切換,對於佔用鎖時間非常短或鎖競爭不激烈的程式碼塊來說效能很高。③缺點:在持有鎖的執行緒長時間佔用鎖或競爭過於激烈時,執行緒會長時間自旋浪費CPU資源,有複雜鎖依賴的情況不適合使用自旋鎖。
Q17:講一講公平鎖與非公平鎖
答:①公平鎖指在分配鎖前檢查是否有執行緒在排隊等待獲取該鎖,優先將鎖分配給排隊時間最長的執行緒。②非公平鎖指在分配鎖時不考慮執行緒排隊等待的情況,直接嘗試獲取鎖,獲取不到鎖就在排到隊尾等待。③因為公平鎖需要在多核情況下維護一個鎖執行緒等待佇列,基於該佇列進行鎖的分配,因此效率比非公平鎖低很多。synchronized是非公平鎖,ReentrantLock預設的lock方法也是非公平鎖。
Q18:講一講讀寫鎖
答:①Lock介面提供的鎖是普通鎖,為了提高效能Java提供了讀寫鎖,讀寫鎖分為讀鎖和寫鎖,讀鎖之間不互斥,讀鎖與寫鎖,寫鎖之間都互斥。②如果系統要求共享資料可以同時支援很多執行緒併發讀,但不能支援很多執行緒併發寫,那麼讀鎖能大大提高效率。如果系統要求共享資料在同一時刻只能有一個執行緒在寫,且寫的過程中不能讀,則需要使用寫鎖。③提高juc的locks包中ReadWriteLock的實現類ReentrantReadWriteLock的readLock()和writeLock()來分別獲取讀鎖和寫鎖。
Q19:講一講共享鎖與排它鎖
答:①共享鎖:允許多個執行緒同時獲取該鎖,併發訪問共享資源,ReentrantReadWriteLock的讀鎖為共享鎖的實現。②排它鎖:也叫互斥鎖 ,每次只允許有一個執行緒獨佔該鎖,ReentrantLock為排它鎖的實現。③排它鎖是一種悲觀的加鎖策略,同一時刻只允許一個執行緒讀取鎖資源,限制了讀操作的併發性,因為併發讀執行緒並不會影響資料的一致性,因此共享鎖採用了樂觀的加鎖策略,允許多個執行讀操作的執行緒同時訪問共享資源。
Q20:鎖有哪些狀態?
答:①無鎖,偏向鎖,輕量級鎖和重量級鎖。②重量級鎖是基於作業系統互斥量實現的,會導致程式在使用者態和核心態之間來回切換,開銷較大,synchronized內部基於監視器實現,監視器基於底層作業系統實現,因此屬於重量級鎖,執行效率不高。JDK1.6後為了減少獲取鎖和釋放鎖帶來的效能消耗提高效能,引入了輕量級鎖和偏向鎖。③輕量級鎖是相對於重量級鎖而言的,核心設計實在沒有多執行緒競爭的前提下,減少重量級鎖的使用來提高效能。適用於執行緒交替執行同步程式碼塊的情況,如果同一時刻有多執行緒訪問同一個鎖,會導致輕量級鎖膨脹成重量級鎖。④偏向鎖用於在某個執行緒獲取某個鎖後,消除這個執行緒鎖重入的開銷,看起來似乎是這個執行緒得到了鎖的偏袒。偏向鎖的主要目的是在同一個執行緒多次獲取某個所的情況下儘量減少輕量級鎖的執行路徑,因為輕量級鎖需要多次CAS操作,而偏向鎖只需要切換ThreadID時執行一次CAS操作,提高效率。出現多執行緒競爭鎖時,JVM會自動撤銷偏向鎖。偏向鎖是進一步提高輕量級鎖效能的。⑤隨著鎖競爭越來越嚴重,鎖可能從偏向鎖升級到輕量級鎖再到重量級鎖,但在Java中只會單向升級不會降級。
Q21:如何進行鎖優化?
答:①減少鎖持有的時間:只在有執行緒安全要求的程式上加鎖來儘量減少同步程式碼塊對鎖的持有時間。②減小鎖粒度:將單個耗時較多的鎖操作拆分為多個耗時較少的鎖操作來增加鎖的並行度,減少同一個鎖上的競爭。在減少鎖的競爭後,偏向鎖、輕量級鎖的使用率才會提高,例如ConcurrentHashMap中的分段鎖。③讀分離:指根據不同的應用場景將鎖的功能進行分離以應對不同的變化,最常見的鎖分離思想就是讀寫鎖,這樣既保證了執行緒安全又提高了效能。④鎖粗化:指為了保障效能,會要求儘可能將鎖的操作細化以減少執行緒持有鎖的時間,但如果鎖分的太細反而會影響效能提升,這種情況下建議將關聯性強的鎖操作集中處理。⑤鎖消除:注意程式碼規範,消除不必要的鎖來提高效能。
Q22:執行緒池是什麼?為什麼需要執行緒池?
答:①在生產中為每一個任務建立一個執行緒存在一些缺陷,如果無限制地大量建立執行緒會消耗很多資源,影響系統穩定性和效能,產生記憶體溢位等問題。②執行緒池是管理一組同構工作執行緒的資源池,執行緒池與工作佇列密切相關,工作佇列中儲存了所有需要等待執行的任務。工作執行緒的任務很簡單,從工作佇列獲取任務,執行任務,返回執行緒池並等待下一次任務。③執行緒池通過重用現有的執行緒,可以在處理多個請求時分攤執行緒在建立和撤銷過程中的開銷,另一個好處是當請求到達時工作執行緒通常已經存在,不會出現等待執行緒而延遲的任務的執行,提高了響應性。通過調整執行緒池的大小,可以建立足夠多的執行緒保持處理器處於忙碌狀態,同時還可以防止執行緒過多導致記憶體資源耗盡。
Q23:建立執行緒池時,ThreadPoolExecutor構造器中都有哪些引數,有什麼含義?
答:①corePoolSize
: 執行緒池核心大小,即在沒有任務執行時執行緒池的大小,並且只有在工作佇列滿了的情況下才會建立超出這個數量的執行緒。②maximumPoolSize
: 執行緒池最大大小,表示可同時活動的執行緒數量的上限。③keepAliveTime
:存活時間,如果某個執行緒的空閒時間超過了存活時間,那麼將被標記為可回收的,並且當執行緒池的當前大小超過基本大小時,這個執行緒將被終止。④unit
: 存活時間的單位,可選的引數為TimeUnit列舉中的幾個靜態變數: NANOSECONDS
、MICROSECONDS
、MILLISECONDS
、SECONDS
。⑤workQueue
: 執行緒池所使用的阻塞佇列。⑥thread factory
:執行緒池使用的建立執行緒工廠方法,可省略,將使用預設工廠。⑦handler
:所用的拒絕執行處理策略,可省略,將使用預設拒絕執行策略。
Q24:執行緒池的阻塞佇列有哪些選擇?
答:①ArrayBlockingQueue
:基於陣列的有界阻塞佇列。②LinkedBlockingQueue
:基於連結串列的有界阻塞佇列。③PriorityBlockingQueue
:支援優先順序排序的無界阻塞佇列。④DelayedWorkQueue
:基於優先順序佇列的無界阻塞佇列。⑤SynchronousQueue
:佇列內部僅允許容納一個元素,用於控制互斥的阻塞佇列。
Q25:執行緒池的拒絕執行策略有哪些選擇?
答:①AbortPolicy()
: 執行緒池預設的拒絕策略,丟擲RejectedExecutionException
異常。②CallerRunsPolicy()
: 重試新增當前的任務,他會自動重複呼叫execute()方法。③DiscardOldestPolicy()
: 拋棄舊的任務,加入新的任務。④DiscardPolicy()
: 直接拋棄當前的任務。
Q26:建立執行緒池的方法有哪些?
答:可以通過Executors的靜態工廠方法建立執行緒池,內部通過過載ThreadExecutorPool不同的構造器建立執行緒池。①newFixedThreadPool
,建立一個固定長度的執行緒池,每當提交一個任務就建立一個執行緒,直到達到執行緒池的最大數量,這時執行緒池的規模將不再變化(如果某個執行緒由於發生了未預期的異常而結束,那麼執行緒池會補充一個新的執行緒)。將執行緒池的核心大小和最大大小都設定為引數中指定的值,建立的執行緒不會超時,使用LinkedBlockingQueue
。②newCachedThreadPool
,建立一個可快取的執行緒池,如果執行緒池的當前規模超過了處理器需求,那麼將回收空閒的執行緒,而當需求增加時,可以新增新的執行緒,執行緒池的規模不存在任何限制。將執行緒池的最大大小設定為Integer.MAX_VALUE
,而將核心大小設定為0,並將超時設為1分鐘,使用SynchronousQueue
,這種方法建立出的執行緒池可被無限擴充套件,並當需求降低時自動收縮。③newSingleThreadExecutor
,一個單執行緒的Executor,建立單個工作者執行緒來執行任務,如果這個執行緒異常結束,會建立另一個執行緒來代替。確保依照任務在佇列中的順序來序列執行。將核心執行緒和最大執行緒數都設定為1,使用LinkedBlockingQueue
。④newScheduledThreadPool
,建立一個固定長度的執行緒池,而且以延遲或定時的方式來執行任務,類似於Timer,使用DelayedWorkQueue
。
Q27:執行緒池的工作原理?
答:①執行緒池剛建立時,裡面沒有一個執行緒。任務佇列是作為引數傳進來的。即使佇列裡面有任務,執行緒池也不會馬上執行它們。②通過 execute(Runnable command)
方法被新增到執行緒池,任務就是一個 Runnable型別的物件,任務的執行方法就是Runnable型別物件的run()方法。③如果workerCount<corePoolSize
,那麼建立並啟動一個執行緒執行新提交的任務。如果workerCount>=corePoolSize
,且執行緒池內的阻塞佇列未滿,那麼將這個任務放入佇列。如果workerCount>=corePoolSize
,且阻塞佇列已滿,若滿足workerCount<maximumPoolSize
,那麼還是要建立並啟動一個執行緒執行新提交的任務。若阻塞佇列已滿,並且workerCount>=maximumPoolSize,則根據 handler所指定的策略來處理此任務,預設的處理方式直接丟擲異常。也就是處理任務的優先順序為: 核心執行緒corePoolSize、任務佇列workQueue、最大執行緒maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務。④當一個執行緒完成任務時,它會從佇列中取下一個任務來執行。⑤當一個執行緒沒有任務可執行,超過一定的時間(keepAliveTime)時,執行緒池會判斷,如果當前執行的執行緒數大於corePoolSize時,那麼這個執行緒會被停用掉,所以執行緒池的所有任務完成後,它最終會收縮到corePoolSize的大小。
Q28:簡述ExecutorService的生命週期
答:①ExecutorService的生命週期有3種狀態:執行、關閉和已終止。②ExecutorService在初始建立時處於執行狀態。③shutdown
方法將執行平緩的關閉過程:不再接受新的任務,同時等待已經提交的任務執行完成——包括那些還未開始執行的任務。shutdownNow
方法將執行粗暴的關閉過程:它將嘗試取消所有執行中的任務,並且不再啟動佇列中尚未開始執行的任務。在ExecutorService關閉後提交的任務將有“拒絕執行處理器REH”來處理,它會拋棄任務,或者使得execute方法丟擲一個未檢查的RejectedExecutionException。④等所有任務都完成後,ExecutorService將轉入終止狀態。可以呼叫awaitTermination
來等待ExecutorService到達終止狀態,或者通過呼叫isTerminated
來輪詢ExecutorService是否已終止。通常在呼叫awaitTermination後會理解呼叫shutdown,從而產生同步地關閉ExecutorService的效果。
Q29:什麼是CAS?
答:①CAS指Compare And Swap,比較並交換。CAS(V,E,N)演算法包括三個引數,V表示要更新的變數的值,E表示預期的值,N表示新值。在且僅在V的值和E相等時才會將V的值設定為N,如果不同則說明已經有其他執行緒做了更改,當前執行緒就什麼也不做。最後CAS返回當前V的真實值。②CAS操作採用了樂觀鎖的思想,有多個執行緒同時使用CAS操作一個共享變數時只有一個執行緒會成功,失敗的執行緒不會被掛起僅會被告知失敗,並且允許再次嘗試,或者放棄操作。基於這樣的原理雖然CAS沒有使用鎖,也可以及時發現其他執行緒的操作進行適當地併發處理。
Q30:CAS有什麼問題?(什麼是ABA問題?)如何解決?
答:①CAS演算法地實現有一個重要前提:需要取出記憶體中某時刻的資料,然後在下一刻進行比較、替換,但在這個時間差內資料可能已經發生了變化,導致ABA問題。②ABA問題指執行緒1從記憶體V位置取出A,這時執行緒2也從記憶體中取出A,並將其首先修改為B,接著又修改為A,這時執行緒1在進行CAS操作時會發現記憶體中資料仍是A,然後執行緒1操作成功。儘管從操作角度來說執行緒1成功了,但是在該過程中實際上資料已發生了變化但並未被感知到,某些應用場景下可能會出現資料不一致的問題。③樂觀鎖通過版本號來解決ABA問題,具體的操作是每次執行資料修改操作時都會帶上一個版本號,如果預期版本號和資料版本號一致就進行操作,並將版本號加1,否則執行失敗。
Q31:講一講wait、sleep、yield、join方法的區別
答:①wait是Object類的方法,呼叫wait方法的執行緒會進入WAITING狀態,只有等待其他執行緒的通知或被中斷後才會解除阻塞,呼叫wait方法會釋放鎖資源。②sleep是Thread類的方法,呼叫sleep方法會導致當前執行緒進入休眠狀態,與wait不同的是該方法不會釋放鎖資源,進入的是TIMED-WAITING狀態。③yiled方法會使當前執行緒讓出CPU時間片給優先順序相同或更高的執行緒,回到RUNNABLE狀態,與其他執行緒一起重新競爭CPU時間片。④join方法用於等待其他執行緒執行終止,如果當前執行緒呼叫了另一個執行緒的join方法,則當前執行緒進入阻塞狀態,當另一個執行緒結束時當前執行緒才能從阻塞狀態轉為就緒態,等待獲取CPU時間片。底層使用的是wait,也會釋放鎖。
Q32:講一講執行緒中斷
答:①interrupt方法用於向執行緒傳送一個終止訊號,會影響該執行緒內部的中斷標識位,這個執行緒本身不會因為呼叫了interrupt方法而改變狀態,狀態的具體變化需要等待接收到中斷標識的程式的處理結果判定。②呼叫interrupt方法不會中斷一個正在執行的執行緒,只會改變內部的中斷標識位的值為true。③當呼叫sleep方法使執行緒處於TIMED-WAITING狀態使,呼叫interrupt方法會丟擲InterruptedException,使執行緒提前結束TIMED-WAITING狀態。在丟擲該異常前將清除中斷標識位,所以在丟擲異常後呼叫isInterrupted方法返回的值是false。④中斷狀態是執行緒固有的一個標識位,可以通過此標識位安全終止執行緒。比如想終止某個執行緒時,先呼叫interrupt方法然後在run方法中根據該執行緒isInterrupted方法的返回值安全終止執行緒。
Q33:什麼是守護執行緒?
答:①守護執行緒是執行在後臺的一種特殊執行緒,獨立於控制終端並且週期性地執行某種任務或等待處理某些已發生的事件。守護執行緒不依賴於終端,但是依賴於JVM,當JVM中僅剩下守護執行緒時,JVM就會退出。②通過setDaemon方法定義一個守護執行緒,守護執行緒的優先順序較低,將一個使用者執行緒設定為守護執行緒必須要在啟動守護執行緒之前。
Q34:start和run方法的區別?
答:①start方法用於啟動執行緒,真正實現了多執行緒,呼叫了start方法後,會在後臺建立一個新的執行緒來執行,不需要等待run方法執行完畢就可以繼續執行其他程式碼。呼叫start方法時,該執行緒處於就緒狀態,並沒有開始執行。②run方法也叫做執行緒體,包含了要執行的執行緒的邏輯程式碼,在呼叫run方法並沒有建立新的執行緒,而是直接執行run方法中的程式碼。
JVM 15
Q1:類的載入機制是什麼?
答:類載入到記憶體中主要有5個階段,分別為①載入:將Class檔案讀取到執行時資料區的方法區內,在堆中建立Class物件,並封裝類在方法區的資料結構的過程。②驗證:主要用於確保Class檔案符合當前虛擬機器的要求,保障虛擬機器自身的安全,只有通過驗證的Class檔案才能被JVM載入。③準備:主要工作是在方法區中為類變數分配記憶體空間並設定類中變數的初始值。④解析:將常量池中的符號引用替換為直接引用。⑤初始化:主要通過執行類構造器的<client>方法為類進行初始化,該方法是在編譯階段由編譯器自動收集類中靜態語句塊和變數的賦值操作組成的。JVM規定,只有在父類的<client>方法都執行成功後,子類的方法才可以被執行。在一個類中既沒有靜態變數賦值操作也沒有靜態語句塊時,編譯器不會為該類生成<client>方法。
Q2:有哪些類載入器,類載入器的載入模型是什麼,有什麼好處?
答:①主要有啟動類載入器,負責載入JAVA_HOME/lib中的類庫;擴充套件類載入器,負責載入JAVA_HOME/lib/ext中的類庫;應用程式類載入器,也稱系統類載入器,負責載入使用者類路徑上指定的類庫;也可以自定義類載入器。②類載入器之間的層次關係叫做雙親委派模型,要求除了頂層的啟動類載入器外其餘的類載入器都應當有自己的父類載入器。一個類收到類載入請求後會層層找父類載入器去嘗試載入,因此所有的載入請求最終都會被傳送到頂層的啟動類載入器,只有當父類載入器反饋自己無法完成載入時子載入器才會嘗試自己去載入。③雙親委派模型的好處是保障類載入的唯一性和安全性,例如載入rt.jar包中的java.lang.Object,無論哪一個類載入最終都會委託給啟動類載入器,這樣就保證了類載入的唯一性。如果存在包名和類名都相同的兩個類,那麼該類就無法被載入。
Q3:簡述JVM的記憶體區域
答:JVM的記憶體區域分為執行緒私有區域(程式計數器、虛擬機器棧、本地方法區)、執行緒共享區域(堆、方法區)和直接記憶體。①程式計數器是一塊很小的記憶體空間,用於儲存當前執行緒執行位元組碼檔案的行號指示器。②虛擬機器棧是描述Java方法執行過程的記憶體模型,幀棧中儲存了區域性變數表,運算元棧,動態連結,方法出口等資訊。③本地方法棧,和虛擬機器棧作用類似,區別是虛擬機器棧為Java方法服務,本地方法棧為Native方法服務。④JVM執行過程中建立的物件和生成的資料都儲存在堆中,堆是被執行緒共享的記憶體區域,也是垃圾回收最主要的記憶體區域。⑤方法區用來儲存常量,靜態變數、類資訊、即時編譯器編譯後的機器碼、執行時常量池等資料。
Q4:哪些情況下類不會初始化?
答:①常量在編譯時會存放在使用該常量的類的常量池,該過程不要呼叫常量所在的類,不會初始化。②子類引用父類的靜態變數時,子類不會初始化,只有父類會初始化。③定義物件陣列,不會觸發該類的初始化。④在使用類名獲取Class物件時不會觸發類的初始化。⑤在使用Class.forName()載入指定的類時,可以通過initialize引數設定是否需要初始化。⑥在使用ClassLoader預設的loadClass方法載入類時不會觸發該類的初始化。
Q5:哪些情況下類會初始化?
答:①建立類的例項。②訪問某個類或介面的靜態變數,或對該靜態變數賦值。③呼叫類的靜態方法。④初始化一個類的子類時(初始化子類,父類必須先初始化)。⑤JVM啟動時被標為啟動類的類。⑥使用反射進行方法呼叫時。
Q6:談談JVM的執行時記憶體
答:JVM的執行時記憶體也叫做JVM堆,從GC角度更將其分為新生代,老年代和永久代。
其中新生代預設佔1/3堆空間,老年代預設佔2/3堆空間,永久代佔非常少的堆空間。
新生代又分為Eden區、ServivorFrom區和ServivorTo區,Eden區預設佔8/10新生代空間,ServivorFrom區和ServivorTo區預設分別佔1/10新生代空間。
Q7:談談新生代是怎麼分割槽的
答:①JVM新建立的物件(除了大物件外)會被存放在新生代,預設佔1/3堆記憶體空間。由於JVM會頻繁建立物件,所以新生代會頻繁觸發MinorGC進行垃圾回收。②新生代又分為Eden區,ServivorFrom區和ServivorTo區。③Eden區:Java新建立的物件首先會被存放在Eden區,如果新建立的物件屬於大物件,則直接將其分配到老年代。大物件的定義和具體的JVM版本、堆大小和垃圾回收策略有關,一般為2KB~128KB,可通過-XX:PretenureSizeThreshold
設定其大小。在Eden區的記憶體空間不足時會觸發MinorGC,對新生代進行一次垃圾回收。②ServivorTo區:保留上一次MinorGC時的倖存者。③ServivorFrom區:將上一次MinorGC時的倖存者作為這一次MinorGC的被掃描者。
Q8:談談新生代的垃圾回收機制
答:新生代的GC過程叫做MinorGC,採用複製演算法實現,具體過程如下:
①把在Eden區和ServivorFrom區中存活的物件複製到ServivorTo區,如果某物件的年齡達到老年代的標準,則將其複製到老年代,同時把這些物件的年齡加1。如果ServivorTo區的記憶體空間不夠,則也直接將其複製到老年代。如果物件屬於大物件,則也直接複製到老年代。②清空Eden區和ServivorFrom區中的物件。③將ServivorFrom區和ServivorTo區互換,原來的ServivorTo區成為下一次GC時的ServivorFrom區。
Q9:談談老年代的垃圾回收機制
答:①老年代主要存放有長生命週期的物件和大物件,老年代的GC叫MajorGC。②在老年代,物件比較穩定,MajorGC不會頻繁觸發。在進行MajorGC前,JVM會進行一次MinorGC,過後仍然出現老年代空間不足或無法找到足夠大的連續記憶體空間分配給新建立的大物件時,會觸發MajorGC進行垃圾回收,釋放JVM的記憶體空間。③MajorGC採用標記清除演算法,該演算法首先會掃描所有物件並標記存活的物件,然後回收未被標記的物件,並釋放記憶體空間。因為要先掃描老年代的所有物件再回收,所以MajorGC的時間較長。容易產生記憶體碎片,在老年代沒有記憶體空間可分配時,會出現記憶體溢位異常。
Q10:談一談永久代
答:①永久代指記憶體的永久儲存區域,主要存放Class和Meta(後設資料)的資訊。Class在類載入時被放入永久代。②永久代和老年代、新生代不同,GC不會在程式執行期間對永久代的記憶體進行清理,這也導致了永久代的記憶體會隨著載入的Class檔案的增加而增加,在載入的Class檔案過多時會出現記憶體溢位異常,比如Tomcat引用jar檔案過多導致JVM記憶體不足而無法啟動。③在JDK1.8中,永久代已經被後設資料區取代。後設資料區的作用和永久代類似,二者最大的區別在於:後設資料區並沒有使用虛擬機器的記憶體,而是直接使用作業系統的本地記憶體。因此元空間的大小不受JVM記憶體的限制,只和作業系統的記憶體有關。④在JDK1.8中,JVM將類的後設資料放入本地記憶體中,將常量池和類的靜態常量放入Java堆中,這樣JVM能夠載入多少後設資料資訊就不再由JVM的最大可用記憶體空間決定,而由作業系統的實際可用記憶體空間決定。
Q11:如何確定物件是否是垃圾?
答:①Java採用引用計數法和可達性分析來確定物件是否應該被回收。引用計數法容易產生迴圈引用的問題,可達性分析通過根搜尋演算法實現。根搜尋演算法以一系列GC Roots的點作為起點向下搜尋,在一個物件到任何GC Roots都沒有引用鏈相連時,說明其已經死亡。根搜尋演算法主要針對棧中的引用、方法區的靜態引用和JNI中的引用展開分析。②引用計數法:在Java中如果要操作物件,就必須先獲取該物件的引用,因此可以通過引用計數法來判斷一個物件是否可以被回收。在為物件新增一個引用時,引用計數加1;在為物件刪除一個引用時,引用計數減1;如果一個物件的引用計數為0,則表示此刻該物件沒有被引用,可以被回收。引用計數法容易產生迴圈引用問題,迴圈引用指兩個物件相互引用,導致它們的引用一直存在,而不能被回收。③可達性分析:為了解決引用計數法的迴圈引用問題,Java還採用了可達性分析來判斷物件是否可以被回收。具體做法是首先定義一些GC Roots物件,然後以這些GC Roots物件作為起點向下搜尋,如果在GC Roots和一個物件之間沒有可達路徑,則稱該物件是不可達的。不可達物件要經過至少兩次標記才能判斷其是否可被回收,如果兩次標記後該物件仍然不可達,則將被垃圾回收器回收。
Q12:有哪些GC演算法?分別有什麼特點?
答:①標記清除演算法:標記出所有需要回收的物件,然後清除可回收的物件。效率較低,並且因為在清除後沒有重新整理可用的記憶體空間,如果記憶體中可被回收的小物件居多,會引起記憶體碎片化問題。②複製演算法:將可用記憶體分為區域1和區域2,將新生成的物件放在區域1,在區域1滿後對區域1進行一次標記,將標記後仍然存活的物件複製到區域2,然後清除區域1。效率較高並且易於實現,解決了記憶體碎片化的問題,缺點是浪費了大量記憶體,同時在系統中存在長生命週期物件時會在兩區域間來回複製影響系統效率。③標記清除演算法:結合了標記清除演算法和複製演算法的優點,標記過程和標記清除演算法一樣,標記後將存活的物件移動到一端,清理另一端。④分代收集演算法:根據物件不同型別把記憶體劃分為不同區域,把堆劃分為新生代和老年代。由於新生代的物件生命週期較短,主要採用複製演算法。將新生代劃分為一塊較大的Eden區和兩塊較小的Survivor區,Servivor區又分為ServivorTo和ServivorFrom區。JVM在執行過程中主要使用Eden和SurvivorFrom區,進行垃圾回收時將這個兩個區域存活的物件複製到SurvivorTo區並清除這兩個區域。老年代主要儲存長生命週期的大物件,因此採用標記清除或標記整理演算法。
Q13:有哪些垃圾回收器?各自有什麼特點?
答:①Serial:單執行緒,基於複製演算法,JVM執行在Client時預設的新生代垃圾收集器。②ParNew:Serial的多執行緒實現,基於複製演算法,JVM執行在Server時預設 的新生代垃圾收集器。③Paraller Scavenge:多執行緒,基於複製演算法,以吞吐量最大化為目標,允許較長時間的STW換取吞吐量。④Serial Old:單執行緒,基於標記整理演算法,是JVM執行在Client模式下預設的老年代垃圾回收器,可和Serial搭配使用。⑤Parall Old:多執行緒,基於標記整理演算法,優先考慮系統的吞吐量。⑥CMS:多執行緒,基於標記清除演算法,為老年代設計,追求最短停頓時間。主要有四個步驟:初始標記、併發標記、重新標記、併發清除。⑥G1:將堆記憶體分為幾個大小固定的獨立區域,在後臺維護了一個優先列表,根據允許的收集時間回收垃圾收集價值最大的區域。相比CMS不會產生記憶體碎片,並且可精確控制停頓時間。分為四個階段:初始標記、併發標記、最終標記、篩選回收。
Q14:Java中有哪些引用型別?
答:①強引用,最常見的引用型別,把一個物件指向一個引用變數時就是強引用。強引用的物件一定為可達性狀態,所以不會被垃圾回收,是記憶體洩漏的主要原因。②軟引用,通過SoftReference實現,如果一個物件只有軟引用,當記憶體空間不足時將被回收。③弱引用,通過WeakReference實現,如果一個物件只有弱引用,在垃圾回收過程中一定會被回收。④虛引用,通過PhantomReference實現,虛引用和引用佇列聯合使用,主要用來跟蹤物件的垃圾回收過程。
Q15:JVM有哪些記憶體回收與回收策略?
答:①物件優先在Eden區分配:大多數情況下物件在新生代Eden區分配,當Eden區沒有足夠空間時,虛擬機器將發起一次MinorGC。②大物件直接進入老年代:大物件是指需要大量連續記憶體空間的Java物件,如很長的字串及陣列。虛擬機器提供了一個引數-XX:PretenureSizeThreshold
,大於該值的物件會直接進入老年代,防止它在新生代之間來回複製。③長期存活的物件進入老年代:虛擬機器給每個物件定義了一個年齡計數器,若物件在Eden區出生、經過第一次MinorGC後仍存活且能被Survivor容納,將被移到Survivor區並且物件年齡設為1。每經過一次MinorGC,年齡就加1。預設在年齡增加到15時晉升到老年代,可通過-XX:MaxTenuringThreshold
設定晉升老年代的年齡閾值。④動態物件年齡判定:如果在Survivor空間中相同年齡所有物件大小超過了該空間的一半,大於等於該年齡的物件就可以直接進入老年代而不用等到達到閾值。⑤空間分配擔保:發生MinorGC前,先判斷老年代最大可用連續空間是否大於新生代所有物件的總空間,如果成立那麼MinorGC是安全的。如果不成立會檢視HandlePromotionFailure
是否允許擔保,如果允許會冒險進行MinorGC,否則改為一次FullGC。
反射與註解 3
Q1:簡述反射的基本概念,優缺點和使用場景。
答:①在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法,對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為Java的反射機制。② 優點是執行時動態獲取類的全部資訊,缺點是破壞了類的封裝性,泛型的約束性。③是框架的核心靈魂,動態代理設計模式採用了反射機制,還有 Spring、Hibernate 等框架也大量使用到了反射機制。
Q2:獲取Class物件有哪幾種方式?能通過Class物件獲取類的哪些資訊?
答:①通過類名.class
②通過物件.getClass()
③通過Class.forName(類的全限名);
④可以通過Class物件獲取類的成員變數,方法或構造器。帶declared的獲取方法可以獲取到類的一個或全部成員變數,方法,構造器,不帶declared的方法只能獲取到類的public修飾的成員變數、方法或構造器,包括父類public修飾的成員變數、方法或構造器。
Q3:註解是什麼,元註解是什麼,有什麼作用?
答:①註解是一種標記,可以使類或介面附加額外的資訊,是幫助編譯器和JVM完成一些特定功能的。②元註解就是自定義註解的註解,包括@Target
:用來約束註解的位置,值是ElementType
列舉類,包括METHOD
方法、VARIABLE
變數、TYPE
類/介面、PARAMETER
方法引數、CONSTRUCTORS
構造器和LOACL_VARIABLE
區域性變數;@Rentention
:用來約束註解的生命週期,值是RetentionPolicy
列舉類,包括:SOURCE
原始碼、CLASS
位元組碼和RUNTIME
執行時;@Documented
:表明這個註解應該被javadoc工具記錄;@Inherited
:表面某個被標註的型別是被繼承的。
IO流 5
Q1:簡單說說File物件表示的是什麼?File類有哪些常用方法?
答:①File物件表示的是作業系統上的檔案或目錄。②獲取:getAbsolutePath()
獲取絕對路徑;getPath()
獲取檔案定義時使用的路徑;getName()
獲取檔名,帶字尾;length()
返回檔案長度,單位是位元組。③判斷:exists()
判斷File物件表示的檔案或目錄是否存在;isDirectory()
判斷是否是目錄; isFile()
判斷是否是檔案。④建立和刪除:createNewFile()
不存在時建立新檔案;delete()
刪除檔案,目錄(非空目錄不能刪除);mkdir()
建立一級目錄;mkdirs()
建立多級目錄,推薦使用;⑤遍歷:list
獲取當前目錄下所有一級檔名稱到一個字串陣列並返回;listFiles
獲取當前目錄下所有一級File物件到File陣列返回。
Q2:英文、數字和中文字元在檔案中分別佔多大的空間?
答:①英文和數字在任何編碼中都佔1個位元組。②中文字元在GBK編碼下佔2個位元組,在UTF-8編碼下佔3個位元組。
Q3:簡述傳統IO有哪些分類?
答:①按流的方向:輸出流:把記憶體中的資料寫出到磁碟檔案或網路介質中;輸入流:把磁碟檔案或網路介質中的資料讀取到記憶體中。②按流的內容:位元組流:流中資料的最小單位是位元組;字元流:流中資料的最小單位是字元(針對文字內容)。頂層的抽象類包括InputStream、OutputStream、Reader、Writer,它們都實現了Closeable介面。③緩衝流(BufferedInputStream/BufferedOutputStream/BufferedReader/BufferedWriter):自帶一個8KB大小的緩衝池,可以將位元組/字元流為緩衝位元組/緩衝字元流。④字元轉換流(InputStreamReader/OutputStreamWriter):可以將對應的位元組流轉換為字元流。⑤列印流:PrintStream,方便快速列印資料,引數是什麼就列印什麼。
Q4:簡述BIO、NIO、AIO的區別和原理
答:①BIO是同步阻塞的,資料的讀寫會阻塞在一個執行緒中,適用於連線數目比較小且固定的架構,對伺服器資源要求高,JDK1.4前的唯一選擇。②NIO是同步非阻塞的,通過Selector監聽Channel上事件的變化,在Channel上有資料發生變化時通知該執行緒進行讀寫操作。適用於連線數目比較多且連線比較短的架構,如聊天伺服器,從 JDK1.4開始支援。③AIO是非同步非阻塞的,非同步是指服務端執行緒接收到客戶端管道後就交給底層處理IO通訊,自己可以做其他事情。適用於連線數目比較多且連線比較長的架構,從JDK1.7開始支援。
Q5:序列化和反序列化是什麼,有什麼要求?
答:①Java在JVM執行時被建立、更新和消耗,當JVM退出時,物件也會隨之銷燬。可以通過Java序列化實現持久化儲存,儲存物件及其狀態資訊到位元組陣列中。②反序列化就是再將位元組陣列中儲存的資訊轉換回Java物件。③要求類必須實現序列化介面,並且序列化和反序列化必須保持序列化的ID一致。④靜態變數和被transient修飾的變數不會被序列化。
JavaWeb 19
Q1:HTTP有哪些特點
答:①HTTP是基於TCP/IP協議的。②HTTP使用的預設埠號是80。③HTTP是基於請求/響應模型的,一次請求對應一次響應。④HTTP是無狀態的,每次請求之間相互獨立,不能互動資料。⑤HTTP1.0每一次請求響應都會建立新的連線,HTTP1.1會複用連線。
Q2:HTTP請求資料的資料格式是什麼?
答:①請求行,包括了請求方式、請求url、請求協議/版本。HTTP協議有7種請求方式,常用的有2種。GET方式,請求引數在請求行中,在url後、 請求的url長度有限制的、不太安全;POST方式,請求引數在請求體中、請求的url長度沒有限制的、相對安全。②請求頭,是客戶端瀏覽器告訴伺服器的一些資訊,常見的請求頭例如User-Agent
,告訴伺服器使用的瀏覽器版本資訊,可以在伺服器端獲取該頭的資訊,解決瀏覽器的相容性問題。Referer
,可以告訴伺服器,當前請求從哪裡來,可以防盜鏈或者進行統計資料。③請求空行,用於分割POST請求的請求頭和請求體的。④請求體(正文),封裝POST請求訊息的請求引數的。
Q3:轉發和重定向的區別?
答:①轉發的特點: 轉發位址列路徑不變、 轉發只能訪問當前伺服器下的資源、轉發是一次請求,可以使用request物件來共享資料。②重定向的特點:位址列發生變化、重定向可以訪問其他站點(伺服器)的資源、重定向是兩次請求,不能使用request物件來共享資料。
Q4:講一講Cookie
答:①Cookie是客戶端會話技術,將資料儲存到客戶端。②建立Cookie物件,繫結資料:new Cookie(String name, String value)
;傳送Cookie物件:response.addCookie(Cookie cookie)
,一次可以傳送多個Cookie;獲取Cookie,拿到資料:request.getCookies()
。③瀏覽器對於單個cookie 的大小有限制(4kb) 以及對同一個域名下的總cookie數量也有限制(20個),cookie一般用於存出少量的不太敏感的資料,在不登入的情況下,完成伺服器對客戶端的身份識別。
Q5:Cookie的生命週期?
答:①預設情況下,當瀏覽器關閉後,Cookie資料被銷燬。②如果想要持久化儲存,可以使用setMaxAge(int seconds)。正數:將Cookie資料寫到硬碟的檔案中,持久化儲存,並指定cookie存活時間,時間到後,cookie檔案自動失效。負數:預設值。零:刪除cookie資訊。
Q6:Cookie可以儲存中文資料嗎?
答:①在tomcat 8 之前cookie中不能直接儲存中文資料,需要將中文資料轉碼—一般採用URL編碼(%E3)。②在tomcat 8 之後,cookie支援中文資料,特殊字元還是不支援,建議使用URL編碼儲存,URL解碼解析。
Q7:Cookie的共享範圍是什麼?
答:①假設在一個tomcat伺服器中,部署了多個web專案,那麼在這些web專案中cookie預設情況下不能共享。通過setPath(String path)設定cookie的獲取範圍,預設情況下,設定為當前的虛擬目錄,如果要共享,則可以將path設定為/
。②不同的tomcat伺服器間cookie共享問題:通過setDomain(String path)設定一級域名,如果一級域名相同,那麼多個伺服器之間cookie可以共享。例如setDomain(".baidu.com")
,那麼tieba.baidu.com和news.baidu.com中cookie可以共享。
Q8:講一講Session
答:①Session是伺服器端會話技術,在一次會話的多次請求間共享資料,將資料儲存在伺服器端的物件中。②獲取HttpSession物件:request.getSession();使用HttpSession物件:Object getAttribute(String name)
、void setAttribute(String name, Object value)
、void removeAttribute(String name)
。③Session的實現是依賴於Cookie的,伺服器是通過cookie中的JESSIONID判斷session是否是同一個的。
Q9:Session的生命週期?當客戶端關閉後,伺服器不關閉,兩次獲取session是否為同一個?客戶端不關閉,伺服器關閉後,兩次獲取的session是同一個嗎?
答:①伺服器關閉、session物件呼叫invalidate() 時銷燬,session預設失效時間 30分鐘。②在預設情況下,當客戶端關閉服務端不關閉時,兩次獲取session值不是同一個。③如果需要相同,則可以建立Cookie,鍵為JSESSIONID,設定最大存活時間,讓cookie持久化儲存。④客戶端不關閉,服務端關閉,兩次獲取的session值也不是同一個。但是要確保資料不丟失。tomcat自動完成以下工作。session的鈍化: 在伺服器正常關閉之前,將session物件序列化到硬碟上。session的活化: 在伺服器啟動後,將session檔案轉化為記憶體中的session物件即可。但是IDEA不支援這種操作,因為每次用IDEA重啟tomcat時會自動刪除catalina_base中work目錄(程式動態生成的檔案),這樣在關閉tomcat時生成的session序列化檔案也會被刪除。
Q10:Session的特點,和Cookie有什麼區別?
答:①Session用於儲存一次會話的多次請求的資料,存在伺服器端。session可以儲存任意型別,任意大小的資料。②Session儲存資料在伺服器端,Cookie儲存資料在客戶端。
Session沒有儲存資料的大小限制,Cookie有資料大小限制。Session儲存資料是安全的,使用Cookie儲存資料相對於使用Session來說不安全。
Q11:EL是什麼?
答:①EL指Expression Language 表示式語言。②EL表示式的作用是替換和簡化jsp頁面中java程式碼的編寫。③EL表示式的語法是:${表示式}
。④JSP預設支援EL表示式,如果要忽略EL表示式,設定JSP中page指令中的isELIgnored="true"
忽略當前jsp頁面中所有的el表示式,也可以通過\${表示式}
忽略當前這個EL表示式。
Q12:JSTL是什麼?
答:①JSTL指JavaServer Pages Tag Library JSP標準標籤庫,是由Apache組織提供的開源的免費的JSP標籤。②JSTL的作用是簡化和替換jsp頁面上的Java程式碼。③使用時首先需要匯入JSTL相關jar包,並引入標籤庫: <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
。
Q13:JSP定義Java程式碼有哪些方式?
答:①<% 程式碼 %>
是JSP頁面中Java程式碼片段的容器,將頁面轉換為servlet類時,會將內容插入到servlet類的jspService()方法中,同時從JSP生成servlet。②<%! 程式碼 %>
用於為JSP頁面宣告全域性的方法和變數。在JSP檔案中,必須先宣告這些變數和方法然後才能使用它們。在頁面轉換中,宣告的方法和變數成為JSP頁面的servlet類中的類成員宣告。語法③<%= 程式碼 %>
用於將轉換為String的Java表示式的值插入到返回給客戶端的響應中。
Q14:JSP的內建物件有哪些?
答:①pageContext,真實型別是PageContext,可以在當前頁面共享資料,還可以獲取其他八個內建物件。②page,真實型別是Object,指當前頁面(Servlet)的物件this。③request,真實型別是HttpServletRequest,封裝客戶端的請求。④response,真實型別是HttpServletResponse,封裝服務端對客戶端的響應。⑤session,真實型別是HttpSession,封裝會話資料資訊。⑥out,真實型別是JspWriter,字元輸出流物件,可以將資料輸出到頁面上,和response.getWriter()類似。response.getWriter()和out的區別:在tomcat伺服器真正給客戶端做出響應之前,會先找response緩衝區資料,再找out緩衝區資料。response.getWriter().write()
資料輸出永遠在out.write()
之前。⑦config,真實型別是ServletConfig,是Servlet的配置物件。⑧exception,真實型別是Throwable,封裝頁面丟擲異常的物件。⑨application,真實型別是ServletContext,封裝伺服器執行環境的物件。
Q15:過濾器是什麼?如何使用?
答:①當訪問伺服器的資源時,過濾器可以將請求攔截下來,完成一些特殊的功能。②需要實現Filter介面,使用註解方式可以在類名上加上註解@WebFilter("攔截路徑")
,使用XML的方式可以配置web.xml中的filter和filter-mapping標籤,設定過濾器類和攔截路徑。
Q16:過濾器的執行流程和生命週期是什麼?
答:①執行流程:執行過濾器,執行放行後的資源,回來執行過濾器放行程式碼下邊的程式碼。②生命週期:init
:在伺服器啟動後,會建立Filter物件,然後呼叫init方法。只執行一次,一般用於載入資源。doFilter
:在每一次請求被攔截資源時執行,會執行多次。destroy
:在伺服器關閉後,Filter物件被銷燬,如果伺服器是正常關閉,則會執行destroy方法。只執行一次。一般用於釋放資源。
Q17:過濾器攔截路徑都有哪些方式?
答:①具體資源路徑:,例如/index.jsp
,只有訪問index.jsp資源時,過濾器才會被執行。②攔截目錄:例如/user/*
,當訪問/user下的所有資源時,過濾器都會被執行。③通過字尾名攔截:例如*.jsp
, 當訪問所有字尾名為jsp資源時,過濾器都會被執行。④攔截所有資源:使用/*
,訪問所有資源時過濾器都會執行。
Q18:AJAX是什麼?
答:①Ajax 是一種在無需重新載入整個網頁的情況下,能夠更新部分網頁的技術。②通過在後臺與伺服器進行少量資料交換,Ajax 可以使網頁實現非同步更新。這意味著可以在不重新載入整個網頁的情況下,對網頁的某部分進行更新。③傳統的網頁(不使用 Ajax)如果需要更新內容,必須過載整個網頁頁面,使用Ajax技術可以提升使用者的體驗。
Q19:JSON是什麼?如何把Java物件轉為JSON?如何把JSON轉回Java物件?
答:①JSON指JavaScript Object Notation JavaScript物件表示法。②JSON現在多用於儲存和交換文字資訊的語法,進行資料的傳輸。③JSON的優勢是想比XML來說佔用空間更小、運算元據更快,更易解析。④將Java物件轉為JSON時,需要先匯入jackson的相關jar包,建立Jackson核心物件 ObjectMapper,之後呼叫ObjectMapper的writeValue(引數,obj)
進行轉換,如果引數是File型別,可以將obj物件轉換為JSON字串,並儲存到指定的檔案中;如果引數是Writer型別,可以將obj物件轉換為JSON字串,並將json資料填充到字元輸出流中;如果引數是OutputStream型別,可以將obj物件轉換為JSON字串,並將JSON資料填充到位元組輸出流中。⑤將JSON轉會Java物件時使用readValue的方法,引數為要轉回的Java物件的Class位元組碼物件。
JavaEE 29
Spring 7
Q1:Spring的IOC和DI是什麼?
答:①IOC即控制反轉,簡單來說就是把物件的控制權委託給spring框架,作用是降低程式碼的耦合度。②DI即依賴注入,是IOC的一種具體實現方式。假設一個Car類需要Engine的物件,那麼一般需要new一個Engine,利用IOC就是隻需要定義一個私有的Engine引用變數,容器會在執行時建立一個Engine的例項物件並將引用自動注入給變數。
Q2:簡述Spring中bean物件的生命週期
答:①Spring對bean進行例項化。②Spring將值和bean的引用注入到其對應的屬性中。③呼叫BeanNameAware的setBeanName方法。④呼叫BeanFactoryAware的setBeanFactory方法。⑤呼叫AppicationContxtAware的setApplicationContext方法。⑥呼叫BeanPostProcessor的post-ProcessBeforeInitialization方法。⑦呼叫InitializingBean的after-PropertiesSet方法。如果bean使用init-method宣告瞭自定義初始化方法,該方法也會被呼叫。⑧呼叫BeanPostProcessor的post-ProcessAfterInitialization方法。⑨使用bean。⑩呼叫DisposableBean的destroy方法,如果bean使用destroy-method宣告瞭自定義銷燬方法,該方法也會被呼叫。
Q3:簡述bean的作用範圍
答:通過scope指定bean的作用範圍,有①singleton:單例的,每次容器返回的物件是同一個。②prototype :多例的,每次返回的物件是新建立的例項。③request:僅作用於HttpRequest,每次Http請求都會建立一個新的bean。④session:僅作用於HttpSession,不同的Session使用不同的例項,相同的Session使用同一個例項。⑤global session :僅作用於HttpSession,所有的Session使用同一個例項。
Q4:BeanFactory和FactoryBean,ApplicationContext的區別?
答:①BeanFactory是一個Factory介面,是用來管理bean的IOC容器或物件工廠,較為古老,不支援spring的一些外掛。BeanFactory使用了延遲載入,適合多例模式。②FactoryBean是一個Bean介面,是一個可以生產或者裝飾物件的工廠Bean,可以通過實現該介面自定義的例項化Bean的邏輯。③ApplicationConext是BeanFactory的子介面,擴充套件了其功能,ApplicationContext是立即載入,適合單例模式。一般推薦使用ApplicationContext。
Q5:使用XML配置有哪些建立Bean物件的方式?
答:①通過預設無參構造器。使用bean標籤,只使用id和class屬性,如果沒有無參構造器會報錯。②使用靜態工廠,通過bean標籤中的class指明靜態工廠,factory-method指明靜態工廠方法。③使用例項工廠,通過bean標籤中的factory-bean指明例項工廠,factory-method指明例項工廠方法。
Q6:依賴注入可以注入哪些資料型別?有哪些注入方式?
答:①可以注入的資料型別有基本資料型別、String、Bean、以及集合等複雜資料型別。②有三種注入方式,第一種是通過構造器注入,通過constructor-arg
標籤實現,缺點是即使不需要該屬性也必須注入;第二種是通過Set方法注入,通過property
標籤實現,優點是建立物件時沒有明確限制,缺點是某個成員變數必須有值,在獲取物件時set方法可能還沒有執行;第三種是通過註解注入,利用@Autowired
自動按型別注入,如果有多個匹配則按照指定bean的id查詢,查詢不到會報錯;@Qualifier
在自動按照型別注入的基礎之上,再按照 Bean 的 id 注入,給成員變數注入時必須搭配@Autowired
,給方法注入時可單獨使用;@Resource
直接按照 Bean 的 id 注入;@Value
用於注入基本資料型別和String。
Q7:有哪些配置Bean的註解,各有什麼區別?
答:①@Component
,把當前類物件存入spring容器中,相當於在 xml 中配置一個 bean。value屬性指定 bean 的 id,如果不指定 value 屬性,預設 id 是當前類的類名,首字母小寫。②@Service
,一般用於業務層。③@Controller
:一般用於表現層。④@Repository
:一般用於持久層。⑤@Controller @Service @Repository
都是針對@Component
的衍生註解,作用及屬性都是一模一樣的,只是提供了更加明確的語義化。
Spring Aop 4
Q1:Spring Aop的基本原理是什麼?
答:Aop即面向切面程式設計,簡單地說就是將程式碼中重複的部分抽取出來,在需要執行的時候使用動態代理的技術,在不修改原始碼的基礎上對方法進行增強。優點是可以減少程式碼的冗餘,提高開發效率,維護方便。Spring會根據類是否實現了介面來判斷動態代理的方式,如果實現了介面會使用JDK的動態代理,核心是InvocationHandler介面和Proxy類,如果沒有實現介面會使用cglib的動態代理,cglib是在執行時動態生成某個類的子類,如果某一個類被標記為final,是不能使用cglib動態代理的。
Q2:簡單解釋一下AOP的相關術語
答:①Joinpoint(連線點):指那些被攔截到的點,在 spring 中這些點指的是方法,因為 spring 只支援方法型別的連線點。例如業務層實現類中的方法都是連線點。②Pointcut(切入點):指我們要對哪些 Joinpoint 進行攔截的定義。例如業務層實現類中被增強的方法都是切入點,切入點一定是連線點,但連線點不一定是切入點。③Advice(通知/增強):指攔截到 Joinpoint 之後所要做的事情。④Introduction(引介):引介是一種特殊的通知,在不修改類程式碼的前提下可以在執行期為類動態地新增一些方法或 Field。⑤Weaving(織入):是指把增強應用到目標物件來建立新的代理物件的過程。spring 採用動態代理織入,而 AspectJ 採用編譯期織入和類裝載期織入。⑥Proxy(代理):一個類被 AOP 織入增強後,就產生一個結果代理類。⑦Target(目標):代理的目標物件。⑧Aspect(切面):是切入點和通知(引介)的結合。
Q3:Spring Aop有哪些相關注解?
答:@Before
前置通知,@AfterThrowing
異常通知,@AfterReturning
後置通知,@After
最終通知,@Around
環繞通知。最終通知會在後置通知之前執行,為解決此問題一般使用環繞通知。
Q4:如何使用XML方式配置AOP?
答:①aop:config
用於宣告開始 aop 的配置。②aop:aspect
用於配置切面。屬性:id
給切面提供一個唯一標識。ref
引用配置好的通知類 bean 的 id。③aop:pointcut
用於配置切入點表示式,就是指定對哪些類的哪些方法進行增強。屬性:expression
用於定義切入點表示式,id
用於給切入點表示式提供一個唯一標識。④aop:before
用於配置前置通知,在切入點方法執行之前執行;aop:after-returning
用於配置後置通知,在切入點方法正常執行之後執行,它和異常通知只能有一個執行;aop:after-throwing
用於配置異常通知,在切入點方法執行產生異常後執行;aop:after
用於配置最終通知,無論切入點方法執行時是否有異常,它都會在其後面執行。
Spring MVC 15
Q1:SpringMVC的作用是什麼?MVC的含義分別是什麼?
答:①springMVC是一種基於Java實現的mvc設計模型的請求驅動型別的輕量級Web層框架,作用包括:引數繫結(獲取請求引數)、呼叫業務層 、進行請求響應。②mvc全名是model view controller模型檢視控制器,model指資料模型,JavaBean的類,用來封裝資料;view指jsp,html等用來展示資料給使用者的介面;controller是整個流程的控制器,用來接收使用者請求以及進行資料校驗等功能。
Q2:要搭建一個最基礎的SpringMVC環境,你是如何配置的?
答:①在pom.xml中匯入以下jar包:org.springframework下的spring-context)、spring-web、spring-webmvc、javax.servlet下的servlet-api、javax.servlet.jsp下的jsp-api以及測試用的junit包。②建立一個springmvc.xml的springconfig配置檔案,開啟包掃描,註冊檢視解析器,配置檢視的字首和字尾。③在web.xml中配置核心控制器,servlet和servlet-mapping的對映等。
Q3:SpringMVC的基礎響應流程是怎樣的?
答:①瀏覽器傳送請求,被 DispatherServlet 捕獲,該 Servlet 並不處理請求,而是把請求轉發出去(控制器類),轉發的路徑是根據請求 URL,匹配@RequestMapping 中的內容②根據執行方法的返回值和檢視解析器(InternalResourceViewResolver),去指定的目錄下查詢指定名稱的檢視檔案,Tomcat伺服器渲染頁面,做出響應。
Q4:SpringMVC響應流程中會涉及到哪些元件?
答:①DispatcherServlet
:前端控制器,使用者請求到達前端控制器,它就相當於 mvc 模式中的 c,dispatcherServlet 是整個流程控制的中心,由它呼叫其它元件處理使用者的請求,dispatcherServlet 的存在降低了元件之間的耦合性。②HandlerMapping
:處理器對映器,負責根據使用者請求找到 Handler 即處理器,SpringMVC 提供了不同的對映器實現不同的對映方式,例如:配置檔案方式,實現介面方式,註解方式等。③Handler
:處理器,它就是我們開發中要編寫的具體業務控制器。由 DispatcherServlet 把使用者請求轉發到 Handler。由Handler 對具體的使用者請求進行處理。④HandlAdapter
:處理器介面卡,
通過 HandlerAdapter 對處理器進行執行,這是介面卡模式的應用,通過擴充套件介面卡可以對更多型別的處理器進行執行⑤View Resolver
:檢視解析器,負責將處理結果生成 View 檢視,View Resolver 首先根據邏輯檢視名解析成物理檢視名,即具體的頁面地址,再生成 View 檢視物件,最後對 View 進行渲染將處理結果通過頁面展示給使用者。⑥View
:檢視,SpringMVC 提供了很多 View 檢視型別的支援,包括:jstlView、freemarkerView、pdfView等。最常用的檢視就是 jsp。一般情況下需要通過頁面標籤或頁面模版技術將模型資料通過頁面展示給使用者,需要由程式設計師根據業務需求開發具體的頁面。
Q5:講一講@RequestMapping註解
答:①作用:建立請求url和處理方法之間的對應關係。②作用位置:類,請求url的第一級訪問目錄,如果不寫相當於根目錄,需要以/
開頭;方法,請求url的第二級訪問目錄,可以不以/
開頭。③屬性:value/path
,繫結路徑,支援多個路徑,一般只配置一個路徑;method
指定訪問方式,可配置多個允許的訪問方式,預設任何方法都支援,例如POST、GET等。
Q6:SpringMVC的引數繫結支援哪些型別,分別有哪些要求?
答:①基本資料型別和String,要求請求引數的引數名必須和控制器中方法的形參名一致,例如請求引數為name,控制器方法的形參也必須為name。②可以是Java物件,要求請求屬性必須和對應的Java類中的成員變數名一致,例如input標籤的name屬性值為id,類中也必須有id這一個成員變數。也可以是Java物件中的List或Map集合。
Q7:如何解決請求引數中文亂碼問題?
答:在web.xml中配置一個過濾器,配置一個filter標籤,使用org.springframework.web.filter
包下的CharacterEncodingFilter
類實現,將<init-param>中的<param-name>設定為encoding,對應的<param-value>設定為UTF-8即可。然後配置對應的fiter-mapping標籤,fiter-name和之前的一樣,<url-pattern>設定為/*
,表示對所有檢視都進行編碼過濾。
Q8:SpringMVC支援哪些Servlet物件作為控制器方法的引數?
答:一共有9個,包括①HttpServletRequest,指客戶端的請求。②HttpServletResponse,指伺服器端的響應。③HttpSession,Java平臺對session機制的實現規範。④Principal,此介面表示主體的抽象概念,它可以用來表示任何實體,例如,個人、公司或登入id。⑤Locale,用於國際化操作的類。⑥InputStream,位元組輸入流。⑦OutputStream,位元組輸出流。⑧Reader,字元輸入流。⑨Writer,字元輸出流。
Q9:SpringMVC的常用註解有哪些?
答:①@RequestParam
:作用是將請求引數和控制器中方法形參繫結(請求引數名和形參名不再要求相同)。屬性包括:name/value,當和請求引數名一致可省略;required指定請求引數是否必填項;defaultValue是未提供請求引數時的預設值。②@RequestBody
:作用是用於獲取請求體的內容,直接使用得到的是key=value形式的字串,把獲取的json資料轉換成pojo物件(get方式不可用)。③@RequestBody
:作用是將控制器中方法返回的物件通過適當的轉換器轉換為指定的格式之後進行響應,通常用來返回JSON資料或者是XML。④@PathVariable
:作用是繫結url中的佔位符,例如請求url中/delete/{id},{id}就是url佔位符。url支援佔位符是spring3.0後加入的,是springmvc支援rest風格url的一個重要標誌。屬性包括name/value 指定url中佔位符名稱;required指定是否必須提供佔位符。⑤@RequestHeader
:作用是獲取指定請求頭的值。屬性:value代表請求頭的名稱。⑥@CookieValue
:作用是用於把指定 cookie 名稱的值傳入控制器方法引數。屬性包括value:指定 cookie 的名稱。required:是否必須有此 cookie。⑦@ModelAttribute
:是 SpringMVC4.3 版本以後加入的,它可以修飾方法和引數,出現在方法上表示當前方法會在控制器的方法執行之前先執行。它可以修飾沒有返回值的方法,也可以修飾有具體返回值的方法。出現在引數上,獲取指定的資料給引數賦值。屬性value用於獲取資料的 key。key 可以是 POJO 的屬性名稱,也可以是 map 結構的 key。
Q10:響應資料的格式有哪些?
答:①字串,控制器中的方法返回字串可以指定邏輯檢視名,通過檢視解析器解析為物理檢視地址,例如返回"success"時可解析為success.jsp頁面。②返回值為空,預設訪問檢視解析器字首+requestmapping路徑+檢視解析器字尾的檢視。③ModelandView,可以通過setViewName()方法設定檢視名實現指定檢視的跳轉。
Q11:SpringMVC中如何實現轉發和重定向,有什麼區別?
答:①前提是控制器方法返回值型別必須是String型別。②轉發到頁面return"forward:
+絕對地址"。轉發到控制器其他方法:return的是"forward:
+類上requestmapping的地址+方法上requestmapping的地址"。③重定向到頁面:return的是"redirect:
+絕對地址",注意不能重定向訪問WEB-INF下的資源。重定向到控制器其他方法:return的是"redirect:
+類上requestmapping的地址+方法上requestmapping的地址"。重定向到外部連結:return的是"redirect:
+連結地址(http://www.qq.com)"。④轉發和重定向的區別是轉發只是一次請求,重定向是兩次請求;轉發位址列不變,重定向位址列將改變;轉發只能到內部資源,重定向可以到內部或外部資源;轉發可以到WEB-INF下資源,重定向不可以。
Q12:SpringMVC實現簡單檔案上傳有哪些要求?
答:①瀏覽器端要求:表單提交方式為post(get有檔案大小限制)。提供檔案上傳框對應的標籤:<input type="file">
。表單的entype
屬性必須為multipart/form-data
。②伺服器端要求:使用**request.getInputStream()**獲取資料。springmvc底層封裝了commons-fileupload檔案上傳工具包。
Q13:SpringMVC的異常處理流程是什麼?
答:Dao層發生的異常會向上丟擲到Service層、Service層的異常會向上丟擲到Controller層,Controller層的異常會繼續向上丟擲到SpringMVC的前端控制器,由前端控制器將異常交給SpringMVC的異常處理器進行處理。如果是自定義的異常處理器,需要實現HandlerExceptionResolver介面,並使用@Component註解配置或在對應的springconfig配置檔案中註冊。
Q14:SpringMVC中的攔截器和攔截器鏈是什麼,和過濾器有什麼區別?
答:①Spring MVC 的攔截器用於對處理器進行預處理和後處理,使用者可以自己定義一些攔截器來實現特定的功能。攔截器鏈就是將攔截器按一定的順序聯結成一條鏈,在訪問被攔截的方法或欄位時,攔截器鏈中的攔截器就會按其之前定義的順序被呼叫。②它和過濾器的區別是:過濾器是 servlet 規範中的一部分,任何 java web 工程都可以使用,攔截器是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用;過濾器在 url-pattern 中配置了/*
之後,可以對所有要訪問的資源攔截,攔截器它是隻會攔截訪問的控制器方法,如果訪問的是 jsp、html、css、image 或者 js 是不會進行攔截的;它也是 AOP 思想的具體應用,如果要想自定義攔截器, 要求必須實現HandlerInterceptor 介面。
Q15:攔截器有哪些常用方法,各自有什麼特點?
答:①preHandle
:按攔截器定義順序呼叫,只要配置了都會呼叫。如果程式設計師決定該攔截器對請求進行攔截處理後還要呼叫其他的攔截器,或者是業務處理器去進行處理,則返回 true,如果不需要再呼叫其他的元件去處理請求,則返回 false。②postHandle
:
按攔截器定義逆序呼叫,在攔截器鏈內所有攔截器返回成功時呼叫。在業務處理器處理完請求後,但是 DispatcherServlet 向客戶端返回響應前被呼叫, 在該方法中對使用者請求 request 進行處理。③afterCompletion
:按攔截器定義逆序呼叫,只有 preHandle 返回 true時才呼叫。在 DispatcherServlet 完全處理完請求後被呼叫,可以在該方法中進行一些資源清理的操作。
Mybatis 3
Q1:延遲載入是什麼?Mybatis支援嗎?
答:①Mybatis支援延遲載入。實際開發過程中很多時候我們並不需要總是在載入某些資訊時就一定要載入其關聯資訊,例如在載入使用者資訊時不是使用者關聯的賬戶資訊不是必需的,此時就可以採用延遲載入。②延遲載入就是在需要用到資料時才進行載入,不需要用到資料時就不載入資料。延遲載入也稱懶載入。③好處:先從單表查詢,需要時再從關聯表去關聯查詢,大大提高資料庫效能,因為查詢單表要比關聯查詢多張錶速度要快。④壞處:因為只有當需要用到資料時,才會進行資料庫查詢,這樣在大批量資料查詢時,因為查詢工作也要消耗時間,所以可能造成使用者等待時間變長,造成使用者體驗下降。
Q2:講一講Mybatis的快取
答:Mybatis的快取分為:①一級快取:指的是Mybatis中SqlSession物件的快取,當我們執行完查詢結果後,查詢的結果會同時存入到SqlSession為我們提供的一塊區域中,該區域的結構是一個Map,當我們再次查詢同樣資料時,Mybatis會先去SqlSession中查詢是否有,有的話直接拿出來用。當SqlSession物件消失時,Mybatis的一級快取也就消失了。一級快取是 SqlSession 範圍的快取,當呼叫 SqlSession 的修改,新增,刪除,commit(),close()等方法時,就會清空一級快取。②二級快取:二級快取是 mapper 對映級別的快取,多個 SqlSession 去操作同一個 Mapper 對映的 sql 語句,多個SqlSession 可以共用二級快取,二級快取是跨 SqlSession 的。
Q3:如何開啟Mybatis的二級快取?
答:①在springconfig配置檔案中,將setting
標籤的cacheEnabled
值設定為true(預設值為true,所以這一步可省略)。②配置相關的 Mapper 對映檔案,使用<cache>
標籤表示當前這個 mapper 對映將使用二級快取。③配置 statement 上面的 useCache 屬性,設定 useCache=”true”
代表當前這個 statement 要使用二級快取,如果不使用二級快取可以設定為 false。針對每次查詢都需要最新的資料 sql,要設定成 useCache=false,禁用二級快取。④如果是使用註解的方式,可以省略第二步,只需要在dao層介面上加上註解@CacheNamespace(blocking=true)
。
資料庫 47
MySQL 21
Q1:MySQL主要有哪些儲存引擎,分別適合哪些應用場景?
答:主要有①MyISAM,是5.5版本之前的預設儲存引擎,支援表級鎖,不支援事務和外來鍵,併發效率較低,讀取資料快,更新資料慢。適合以讀操作為主,並且對併發性要求較低的應用。②InnoDB,MySQL目前的預設儲存引擎,支援行級鎖、事務和外來鍵,併發效率好。適合對事務的完整性和併發性、資料的準確性要求比較高,增刪操作多的應用。③Memory,所有的資料都儲存在記憶體中,訪問速度快,一旦服務關閉資料將丟失。適合更新不太頻繁的資料量小的表用來快速得到訪問結果。④Archive、Federated等。
Q2:索引是什麼?
答:MySQL官方對索引的定義為:索引(index)是幫助MySQL高效獲取資料的資料結構(有序)。在資料之外,資料庫系統還維護者滿足特定查詢演算法的資料結構,這些資料結構以某種方式引用(指向)資料, 這樣就可以在這些資料結構上實現高階查詢演算法,這種資料結構就是索引。
Q3:索引的優缺點有哪些?
答:①優勢:提高資料檢索的效率,降低資料庫的IO成本。通過索引列對資料進行排序,降低資料排序的成本,降低CPU的消耗。②劣勢:實際上索引也是一張表,該表中儲存了主鍵與索引欄位,並指向實體類的記錄,所以索引列也是要佔用空間的。 雖然索引大大提高了查詢效率,同時卻也降低更新表的速度,如對錶進行INSERT、UPDATE、DELETE。因為更新表時,MySQL 不僅要儲存資料,還要儲存一下索引檔案每次更新新增了索引列的欄位,都會調整因為更新所帶來的鍵值變化後的索引資訊。
Q4:MySQL支援哪幾種索引?
答:①BTREE 索引 : 最常見的索引型別,大部分索引都支援 B 樹索引。②HASH 索引:只有Memory引擎支援 , 使用場景簡單 。③R-tree 索引(空間索引):空間索引是MyISAM引擎的一個特殊索引型別,主要用於地理空間資料型別,通常使用較少,不做特別介紹。④Full-text (全文索引) :全文索引也是MyISAM的一個特殊索引型別,主要用於全文索引,InnoDB從Mysql5.6版本開始支援全文索引。
Q5:B+樹是什麼和B樹有什麼區別?
答:①BTree又叫多路平衡搜尋樹,一顆m叉的BTree特性如下: 樹中每個節點最多包含m個孩子。 除根節點與葉子節點外,每個節點至少有[ceil(m/2)]個孩子。若根節點不是葉子節點,則至少有兩個孩子。所有的葉子節點都在同一層。每個非葉子節點由n個key與n+1個指標組成,其中[ceil(m/2)-1] <= n <= m-1。②B+Tree為BTree的變種,B+Tree與BTree的區別為: n叉B+Tree最多含有n個key,而BTree最多含有n-1個key。 B+Tree的葉子節點儲存所有的key資訊,依key大小順序排列。所有的非葉子節點都可以看作是key的索引部分。③由於B+Tree只有葉子節點儲存key資訊,查詢任何key都要從root走到葉子。所以B+Tree的查詢效率更加穩定。
Q6:MySQL的索引對B+樹做了哪些優化?
答:MySql索引資料結構對經典的B+Tree進行了優化。在原B+Tree的基礎上,增加一個指向相鄰葉子節點的連結串列指標,就形成了帶有順序指標的B+Tree,提高區間訪問的效能。
Q7:索引有哪些分類?
答:①單值索引 :即一個索引只包含單個列,一個表可以有多個單列索引。②唯一索引 :索引列的值必須唯一,但允許有空值。③複合索引 :即一個索引包含多個列。
Q8:資料庫的索引建立有哪些設計原則?
答:①對查詢頻次較高,資料量較大的表建立索引。②限制索引數量:對於增刪改操作較多的表,如果索引過多將需要很高的維護代價,降低操作效率,增加操作耗時。③利用最左字首:如果索引欄位值過長,會降低索引的執行效率。④刪除不常用索引。⑤使用唯一索引,區分度越高,效率越高。⑤使用短索引,如果索引值很長則佔用磁碟變大,會影響效。⑥為常作為查詢條件、經常需要排序、分組和聯合操作的欄位建立索引。⑦儘量擴充套件現有索引,聯合索引的效率高於多個獨立索引。
Q9:索引在什麼情況下會失效?
答:①複合索引未使用最左列索引時或跳躍使用時失效,例如以name,age和sex欄位建立索引,只使用age和sex或只使用name和sex時索引失效。②在索引上進行運算或函式操作時索引失效。③數字字元沒有加單引號索引失效,因為MySQL查詢優化器會自動進行型別轉換。④LIKE以%開頭的查詢索引失效,%在前時執行計劃更傾向於使用全表掃描。⑤OR的前後沒有同時使用索引時索引失效。⑥當全表掃描比使用索引速度更快時會使用全表掃描。
Q10:簡述資料庫三大正規化
答:①第一正規化:如果每列都是不可再分的最小資料單元,則滿足第一正規化。例如address:中國北京可拆分為兩列,countyr:中國,city:北京。②第二正規化:在第一正規化的基礎上,規定表中的非主鍵列不存在對主鍵的部分依賴,即第二正規化要求每個表只描述一件事情。例如訂單表:訂單編號、產品編號、訂單日期、產品價格可拆分為訂單表:訂單編號、訂單日期和產品表:產品編號、產品價格。③第三正規化:滿足第一和第二正規化,並且表中的列不存在對非主鍵列的傳遞依賴。例如訂單表:訂單編號、訂單日期、使用者編號、使用者姓名可優化為訂單表:訂單編號、訂單日期、使用者姓名。
Q11:MySQL資料庫的隔離級別有哪些?分別有什麼特點?
答:①未提交讀,一個事務會讀取到另一個事務沒有提交的資料,存在髒讀、不可重複讀、幻讀的問題。②已提交讀,一個事務可以讀取到另一個事務已經提交的資料,解決了幻讀的問題,存在不可重複讀、幻讀的問題。③可重複讀,MySQL預設的隔離級別,在一次事務中讀取同一個資料結果是一樣的,解決了不可重複讀的問題,存在幻讀問題。④可序列化,每次讀都需要獲得表級共享鎖,讀寫互相阻塞,效率低,解決了幻讀問題。
Q12:讀取資料庫時可能出現哪些問題?
答:①髒讀,一個事務中會讀取到另一個事務中還沒有提交的資料,如果另一事務最終回滾了資料,那麼所讀取到的資料就是無效的。②不可重複讀,一個事務中可以讀取到另一個事務中已經提交的資料,在同一次事務中對同一資料讀取的結果可能不同。③幻讀,一個事務在讀取資料時,當另一個事務在表中插入了一些新資料時再次讀取表時會多出幾行,如同出現了幻覺。
Q13:簡述事務的ACID屬性
答:①Atomicity表示原子性,事務中的所有操作都是不可分割的原子單位,要麼全部成功,要麼全部失敗。②Consistency表示一致性,無論正常執行還是異常退出,事務執行前後資料的完整性必須保持一致,比如轉賬前後雙方的總金額是不變的。③Isolation表示隔離性,併發操作中不同事務是互相隔離的,之間不會互相影響。④Durability表示永續性,事務操作完成後資料就會被持久化修改到永久儲存中。
Q14:簡述主從複製的基本原理
答:①主從複製是指一臺伺服器充當主資料庫伺服器,另外一臺或多臺伺服器充當從資料庫伺服器,主伺服器中的資料自動複製到從伺服器中。對於多級複製,資料庫伺服器既可充當主機也可充當從機。②MySQL主從複製的基礎是主伺服器對資料庫修改二進位制記錄,從伺服器通過主伺服器的二進位制日誌自動執行更新。
Q15:MySQL有哪些鎖?
答:①按操作型別可以分為讀鎖(共享鎖S)和寫鎖(排它鎖X)。讀鎖:對同一份資料,多個讀操作可以同時進行而不會互相影響。寫鎖:當前操作沒有完成之前,會阻塞其他讀鎖和寫鎖。②按操作粒度分為行鎖、表鎖、頁鎖。行鎖指對某行資料加鎖,是一種排它鎖。表鎖指對當前操作的整張表加鎖,實現簡單,資源消耗較少。③頁鎖的鎖定粒度介於行鎖和表鎖之間,一次鎖定相鄰的一組記錄。
Q16:檢視是什麼?和普通的表有什麼區別?
答:①檢視(View)是一種虛擬存在的表。檢視並不在資料庫中實際存在,行和列資料來自定義檢視的查詢中使用的表,並且是在使用檢視時動態生成的。通俗的講,檢視就是一條SELECT語句執行後返回的結果集。所以我們在建立檢視的時候,主要的工作就落在建立這條SQL查詢語句上。②檢視相對於普通的表的優勢主要包括以下幾項:簡單:使用檢視的使用者完全不需要關心後面對應的表的結構、關聯條件和篩選條件,對使用者來說已經是過濾好的複合條件的結果集。安全:使用檢視的使用者只能訪問他們被允許查詢的結果集,對錶的許可權管理並不能限制到某個行某個列,但是通過檢視就可以簡單的實現。資料獨立:一旦檢視的結構確定了,可以遮蔽表結構變化對使用者的影響,源表增加列對檢視沒有影響;源表修改列名,則可以通過修改檢視來解決,不會造成對訪問者的影響。
Q17:儲存過程和函式是什麼?有什麼區別?
答:①儲存過程和函式是 事先經過編譯並儲存在資料庫中的一段 SQL 語句的集合,呼叫儲存過程和函式可以簡化應用開發人員的很多工作,減少資料在資料庫和應用伺服器之間的傳輸,對於提高資料處理的效率是有好處的。 ②兩者的區別在於函式必須有返回值,而儲存過程沒有返回值。
Q18:觸發器是什麼?
答:①觸發器是與表有關的資料庫物件,指在 insert/update/delete 之前或之後,觸發並執行觸發器中定義的SQL語句集合。觸發器的這種特性可以協助應用在資料庫端確保資料的完整性 , 日誌記錄 , 資料校驗等操作 。②使用別名 OLD 和 NEW 來引用觸發器中發生變化的記錄內容,這與其他的資料庫是相似的。現在觸發器還只支援行級觸發,不支援語句級觸發。
Q19:瞭解MySQL的體系結構嗎?
答:① 連線層:最上層是一些客戶端和連結服務,包含本地sock 通訊和大多數基於客戶端/服務端工具實現的類似於 TCP/IP的通訊。主要完成一些類似於連線處理、授權認證、及相關的安全方案。在該層上引入了執行緒池的概念,為通過認證安全接入的客戶端提供執行緒。同樣在該層上可以實現基於SSL的安全連結。伺服器也會為安全接入的每個客戶端驗證它所具有的操作許可權。②服務層:第二層架構主要完成大多數的核心服務功能,如SQL介面,並完成快取的查詢,SQL的分析和優化,部分內建函式的執行。所有跨儲存引擎的功能也在這一層實現,如 過程、函式等。在該層,伺服器會解析查詢並建立相應的內部解析樹,並對其完成相應的優化如確定表的查詢的順序,是否利用索引等, 最後生成相應的執行操作。如果是select語句,伺服器還會查詢內部的快取,如果快取空間足夠大,這樣在解決大量讀操作的環境中能夠很好的提升系統的效能。③ 引擎層:儲存引擎層, 儲存引擎真正的負責了MySQL中資料的儲存和提取,伺服器通過API和儲存引擎進行通訊。不同的儲存引擎具有不同的功能,這樣我們可以根據自己的需要,來選取合適的儲存引擎。④儲存層:資料儲存層, 主要是將資料儲存在檔案系統之上,並完成與儲存引擎的互動。
Q20:儲存引擎應當怎樣進行選擇?
答:①在選擇儲存引擎時,應該根據應用系統的特點選擇合適的儲存引擎。對於複雜的應用系統,還可以根據實際情況選擇多種儲存引擎進行組合。以下是幾種常用的儲存引擎的使用環境。②InnoDB : 是Mysql的預設儲存引擎,用於事務處理應用程式,支援外來鍵。如果應用對事務的完整性有比較高的要求,在併發條件下要求資料的一致性,資料操作除了插入和查詢意外,還包含很多的更新、刪除操作,那麼InnoDB儲存引擎是比較合適的選擇。InnoDB儲存引擎除了有效的降低由於刪除和更新導致的鎖定, 還可以確保事務的完整提交和回滾,對於類似於計費系統或者財務系統等對資料準確性要求比較高的系統,InnoDB是最合適的選擇。③MyISAM : 如果應用是以讀操作和插入操作為主,只有很少的更新和刪除操作,並且對事務的完整性、併發性要求不是很高,那麼選擇這個儲存引擎是非常合適的。④MEMORY:將所有資料儲存在RAM中,在需要快速定位記錄和其他類似資料環境下,可以提供幾塊的訪問。MEMORY的缺陷就是對錶的大小有限制,太大的表無法快取在記憶體中,其次是要確保表的資料可以恢復,資料庫異常終止後表中的資料是可以恢復的。MEMORY表通常用於更新不太頻繁的小表,用以快速得到訪問結果。⑤MERGE:用於將一系列等同的MyISAM表以邏輯方式組合在一起,並作為一個物件引用他們。MERGE表的優點在於可以突破對單個MyISAM表的大小限制,並且通過將不同的表分佈在多個磁碟上,可以有效的改善MERGE表的訪問效率。這對於儲存諸如資料倉儲等VLDB環境十分合適。
Q21:優化SQL的步驟瞭解嗎?
答:①檢視SQL執行頻率。②定位低效率執行SQL。可以通過以下兩種方式:慢查詢日誌 : 通過慢查詢日誌定位那些執行效率較低的 SQL 語句。show processlist
: 慢查詢日誌在查詢結束以後才記錄,所以在應用反映執行效率出現問題的時候查詢慢查詢日誌並不能定位問題,可以使用show processlist
命令檢視當前MySQL在進行的執行緒,包括執行緒的狀態、是否鎖表等,可以實時地檢視 SQL 的執行情況,同時對一些鎖表操作進行優化。③通過以上步驟查詢到效率低的 SQL 語句後,可以通過 EXPLAIN或者 DESC命令獲取 MySQL如何執行 SELECT 語句的資訊,包括在 SELECT 語句執行過程中表如何連線和連線的順序。④Mysql從5.0.37版本開始增加了對 show profiles
和 show profile
語句的支援。show profiles
能夠在做SQL優化時幫助我們瞭解時間都耗費到哪裡了。⑤MySQL5.6提供了對SQL的跟蹤trace, 通過trace檔案能夠進一步瞭解為什麼優化器選擇A計劃, 而不是選擇B計劃。開啟trace , 設定格式為 JSON,並設定trace最大能夠使用的記憶體大小,避免解析過程中因為預設記憶體過小而不能夠完整展示。
JDBC 10
Q1:瞭解JDBC嗎?
答:①JDBC(Java Database Connectivity)是一個獨立於特定資料庫管理系統、通用的SQL資料庫存取和操作的公共介面(一組API),定義了用來訪問資料庫的標準Java類庫(java.sql,javax.sql),使用這些類庫可以以一種標準的方法方便地訪問資料庫資源。
②JDBC為訪問不同的資料庫提供了統一的途徑,為開發者遮蔽了一些細節問題。③JDBC的目標是使Java程式設計師使用JDBC可以連線任何提供了JDBC驅動程式的資料庫系統,這樣就使得程式設計師無需對特定的資料庫系統的特點有過多的瞭解,從而大大簡化和加快了開發過程。
Q2:JDBC的操作步驟?
答:①匯入相應的jar包。②載入、註冊sql驅動。③獲取Connection連線物件。④建立Statement物件並執行SQL語句。⑤使用ResultSet物件獲取查詢結果集。⑥依次關閉ResultSet、Statement、Connection物件。
Q3:Statement和PrepatedStatement的區別是什麼?
答:①Statement:用於執行靜態 SQL 語句並返回它所生成結果的物件。②PrepatedStatement:SQL 語句被預編譯並儲存在此物件中,可以使用此物件多次高效地執行該語句。③使用Statement運算元據表存在弊端:存在拼串操作,繁瑣;存在SQL隱碼攻擊問題。④PreparedStatement程式碼的可讀性和可維護性更強,能實現更高效的批量操作。DBServer會對預編譯語句提供效能優化。因為預編譯語句有可能被重複呼叫,所以語句在被DBServer的編譯器編譯後的執行程式碼被快取下來,那麼下次呼叫時只要是相同的預編譯語句就不需要編譯,只要將引數直接傳入編譯過的語句執行程式碼中就會得到執行。在statement語句中,每執行一次都要對傳入的語句編譯一次。⑤PreparedStatement 可以防止 SQL 注入,還可以操作Blob類資料。
Q4:ResultSet物件儲存的是什麼?
答:①PreparedStatement 的 executeQuery()方法,查詢結果是一個ResultSet 物件,
ResultSet 物件以邏輯表格的形式封裝了執行資料庫操作的結果集,ResultSet 介面由資料庫廠商提供實現。②ResultSet 返回的實際上就是一張資料表,有一個指標指向資料表的第一條記錄的前面。③ResultSet 物件維護了一個指向當前資料行的遊標,初始的時候,遊標在第一行之前,可以通過 ResultSet 物件的next()方法移動到下一行。呼叫 next()方法檢測下一行是否存在。若存在,該方法返回true,且指標下移,相當於Iterator物件的 hasNext() 和 next()方法的結合體。可以通過呼叫對應的getXxx()獲取每一列的值。
Q5:ResultSetMetaData物件儲存的是什麼?
答:①可用於獲取關於 ResultSet 物件中列的型別和屬性資訊的物件。②通過呼叫ResultSet物件的getMetaData()方法獲得ResultSetMetaData物件,getColumnName(int column)
:獲取指定列的名稱,getColumnLabel(int column)
:獲取指定列的別名
,getColumnCount()
:返回當前 ResultSet 物件中的列數。
Q6:JDBC要釋放的資源有哪些,釋放的順序是什麼?
答:①釋放ResultSet, Statement,Connection。②資料庫連線(Connection)是非常稀有的資源,用完後必須馬上釋放,如果Connection不能及時正確的關閉將導致系統問題。Connection的使用原則是儘量晚建立,儘量早的釋放。③可以在finally中釋放資源,保證及時其他程式碼出現異常,資源也一定能被釋放。
Q7:資料庫連線池是什麼?它的工作原理是怎樣的?
答:①傳統開發模式存在的問題:普通的JDBC資料庫連線使用 DriverManager 來獲取,每次向資料庫建立連線的時候都要將 Connection 載入到記憶體中,資料庫的連線資源並沒有得到很好的重複利用。若在高併發情況下,頻繁進行資料庫連線操作將佔用很多的系統資源,嚴重的甚至會造成伺服器的崩潰。對於每一次資料庫連線,使用完後都得斷開。否則,如果程式出現異常而未能關閉,將會導致資料庫系統中的記憶體洩漏,最終將導致重啟資料庫。不能控制被建立的連線物件數,系統資源會被毫無顧及的分配出去,如連線過多,也可能導致記憶體洩漏,伺服器崩潰。②為解決傳統開發中的資料庫連線問題,可以採用資料庫連線池技術。基本思想:就是為資料庫連線建立一個“緩衝池”。預先在緩衝池中放入一定數量的連線,當需要建立資料庫連線時,只需從“緩衝池”中取出一個,使用完畢之後再放回去。資料庫連線池負責分配、管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而不是重新建立一個。③資料庫連線池在初始化時將建立一定數量的資料庫連線放到連線池中,這些資料庫連線的數量是由最小資料庫連線數來設定的。無論這些資料庫連線是否被使用,連線池都將一直保證至少擁有這麼多的連線數量。連線池的最大資料庫連線數量限定了這個連線池能佔有的最大連線數,當應用程式向連線池請求的連線數超過最大連線數量時,這些請求將被加入到等待佇列中。
Q8:資料庫連線池有哪些優點?
答:①資源重用:由於資料庫連線得以重用,避免了頻繁建立,釋放連線引起的大量效能開銷。在減少系統消耗的基礎上,另一方面也增加了系統執行環境的平穩性。② 更快的系統反應速度:資料庫連線池在初始化過程中,往往已經建立了若干資料庫連線置於連線池中備用。此時連線的初始化工作均已完成。對於業務請求處理而言,直接利用現有可用連線,避免了資料庫連線初始化和釋放過程的時間開銷,從而減少了系統的響應時間。當資料庫訪問結束後,程式還是像以前一樣關閉資料庫連線:conn.close(); 但conn.close()並沒有關閉資料庫的物理連線,它僅僅把資料庫連線釋放,歸還給了資料庫連線池。
③ 新的資源分配手段:對於多應用共享同一資料庫的系統而言,可在應用層通過資料庫連線池的配置,實現某一應用最大可用資料庫連線數的限制,避免某一應用獨佔所有的資料庫資源。④ 統一的連線管理,避免資料庫連線洩漏:在較為完善的資料庫連線池實現中,可根據預先的佔用超時設定,強制回收被佔用連線,從而避免了常規資料庫連線操作中可能出現的資源洩露。
Q9:資料庫連線池有哪些分類?
答:①JDBC 的資料庫連線池使用 javax.sql.DataSource 來表示,DataSource 只是一個介面,該介面通常由伺服器(Weblogic, WebSphere, Tomcat)提供實現,也有一些開源組織提供實現。②DBCP 是Apache提供的資料庫連線池。tomcat 伺服器自帶dbcp資料庫連線池。速度相對c3p0較快,但因自身存在BUG,Hibernate3已不再提供支援。③C3P0 是一個開源組織提供的一個資料庫連線池,速度相對較慢,穩定性還可以。hibernate官方推薦使用。④Druid 是阿里提供的資料庫連線池,集合了DBCP 、C3P0 、Proxool 的優點。
Q10:資料來源DataSource和資料庫連線Connection有什麼區別?
答:①DataSource 通常被稱為資料來源,它包含連線池和連線池管理兩個部分,習慣上也經常把 DataSource 稱為連線池。DataSource用來取代DriverManager來獲取Connection,獲取速度快,同時可以大幅度提高資料庫訪問速度。②資料來源和資料庫連線不同,資料來源無需建立多個,它是產生資料庫連線的工廠,因此整個應用只需要一個資料來源即可。
Redis 16
Q1:什麼是NoSQL?列舉幾個你知道的NoSQL資料庫。
答:①許多網站在海量使用者訪問的高併發情況下出現崩潰問題,根本原因是關係型資料庫。關係型資料庫有效能瓶頸:磁碟IO效能低下、擴充套件瓶頸:資料關係複雜,擴充套件性差,不便於大規模叢集。②NoSQL即Not-Only SQL,泛指非關係型資料庫,作為關係型資料庫的補充,降低了磁碟IO次數——使用記憶體儲存、去除資料間關係——不儲存關係,僅儲存資料。③NoSQL的特徵:特徵:可擴容,可伸縮;大資料量下高效能;靈活的資料模型;高可用。④常見的NoSQL資料庫:Redis、memcache、HBase、MongoDB。
Q2:簡單講講Redis的含義
答:①Redis (REmote DIctionary Server) 是用 C 語言開發的一個開源的高效能鍵值對(key-value)資料庫。②Redis資料庫中的資料間沒有必然的關聯關係,內部採用單執行緒機制進行工作,效能比較高,支援持久化儲存。③支援多種資料型別,包括字串型別 string、列表型別 list、雜湊型別 hash、集合型別 set、有序集合型別 sorted_set。
Q3:Redis有哪些應用場景?
答:①為熱點資料加速查詢(主要場景),如熱點商品、熱點新聞、熱點資訊、推廣類等高訪問量資訊等。②應用於任務佇列,如秒殺、搶購、購票排隊等。③即時資訊查詢,如排行榜、各類網站訪問統計、公交到站資訊、線上人數資訊(聊天室、網站)、裝置訊號等。④時效性資訊控制,如驗證碼控制、投票控制等。⑤分散式資料共享,如分散式叢集架構中的 session 分離以及訊息佇列、分散式鎖等。
Q4:簡述string型別的基本操作和注意事項
答:①儲存的資料:單個資料,最簡單常用的資料儲存型別。儲存資料的格式:一個儲存空間儲存一個資料。儲存內容:通常使用字串,如果字串以整數的形式展示,可以作為數字操作使用。②新增/修改資料:set key value
、獲取資料:get key
、刪除資料:del key
、新增/修改多個資料:mset key1 value1 key2 value2 ...
、獲取多個資料:mget key1 key2 …
、獲取資料字元個數(字串長度):strlen key
、追加資訊到原始資訊後部(如果原始資訊存在就追加,否則新建):append key value
。③string在redis內部儲存預設就是一個字串,當遇到增減類操作incr
,decr
時會轉成數值型進行計算。redis所有的操作都是原子性的,採用單執行緒處理所有業務,命令是一個一個執行的,因此無需考慮併發 帶來的資料影響。注意:按數值進行操作的資料,如果原始資料不能轉成數值,或超越了redis 數值上限範圍(java中long型資料最大值,Long.MAX_VALUE)將報錯。
Q5:簡述hash型別的基本操作和注意事項
答:①儲存需求:對一系列儲存的資料進行編組,方便管理,一般儲存物件資訊。儲存結構:一個儲存空間儲存多個鍵值對資料。底層使用雜湊表結構實現資料儲存。②如果field數量較少,儲存結構優化為類陣列結構;如果field數量較多,儲存結構使用HashMap結構。③新增/修改資料:hset key field value
、獲取資料:hget key field
,hgetall key
、 刪除資料:hdel key field1 [field2]
、新增/修改多個資料:hmset key field1 value1 field2 value2 …
、 獲取多個資料:hmget key field1 field2 …
、獲取雜湊表中欄位的數量:hlen key
、獲取雜湊表中是否存在指定的欄位:hexists key field
。③hash型別下的value只能儲存字串,不允許儲存其他資料型別,不存在巢狀現象。如果資料未獲取到, 對應的值為(nil)。每個 hash 可以儲存 2^32 - 1 個鍵值對。hash型別十分貼近物件的資料儲存形式,並且可以靈活新增刪除物件屬性。但hash設計初衷不是為了儲存大量物件而設計的,不可濫用,更不可以將hash作為物件列表使用。hgetall 操作可以獲取全部屬性,如果內部field過多,遍歷整體資料效率就很會低,有可能成為資料訪問瓶頸。
Q6:簡述list型別的基本操作和注意事項
答:①儲存需求:儲存多個資料,並對資料進入儲存空間的順序進行區分。儲存結構:一個儲存空間儲存多個資料,且通過資料可以體現進入順序。儲存多個資料,底層使用雙向連結串列儲存結構實現。②新增/修改資料:lpush key value1 [value2] …
,rpush key value1 [value2] …
、獲取資料:lrange key start stop
,lindex key index
,llen key
、獲取並移除資料:lpop key
,rpop key
。獲取資料時可以設定等待時間,list為空時等待獲取。移除指定資料:lrem key count value
。③list中儲存的資料都是string型別的,資料總容量是有限的,最多2^32- 1 個元素(4294967295)。list具有索引的概念,但是運算元據時通常以佇列的形式進行入隊出隊操作,或以棧的形式進行入棧出棧操作。獲取全部資料操作結束索引設定為-1。list可以對資料進行分頁操作,通常第一頁的資訊來自於list,第2頁及更多的資訊通過資料庫的形式載入。
Q7:簡述set型別的基本操作和注意事項
答:①儲存需求:儲存大量的資料,在查詢方面提供更高的效率。儲存結構:能夠儲存大量的資料,高效的內部儲存機制,便於查詢。與hash儲存結構完全相同,僅儲存鍵,不儲存值(nil),並且值是不允許重複的。②新增資料:sadd key member1 [member2]
、獲取全部資料:smembers key
、刪除資料:srem key member1 [member2]
、獲取集合資料總量:scard key
、判斷集合中是否包含指定資料:sismember key member
。③set 型別不允許資料重複,如果新增的資料在 set 中已經存在,將只保留一份。set 雖然與hash的儲存結構相同,但是無法啟用hash中儲存值的空間。
Q8:簡述sorted-set型別的相關操作和注意事項
答:①儲存需求:資料排序有利於資料的有效展示,需要提供一種可以根據自身特徵進行排序的方式。儲存結構:新的儲存模型,可以儲存可排序的資料,在set的儲存結構基礎上新增可排序欄位。②新增資料:zadd key score1 member1 [score2 member2]
、獲取全部資料:zrange key start stop [WITHSCORES]
,zrevrange key start stop [WITHSCORES]
、刪除資料:zrem key member [member ...]
。③score儲存的資料儲存空間是64位,超過該範圍的話score儲存的資料也可以是一個雙精度的double值,但可能會丟失精度,使用時候要慎重。sorted_set 底層儲存還是基於set結構的,因此資料不能重複,如果重複新增相同的資料,score值將被反覆覆蓋,保留最後一次修改的結果。
Q9:Key有哪些通用指令?
答:①刪除指定key:del key
、獲取key是否存在:exists key
、獲取key的型別:type key
。②為指定key設定有效期:expire key seconds
單位秒,pexpire key milliseconds
單位毫秒、獲取key的有效時間:ttl key
如果key不存在或key失效顯示-2,沒設定有效期或永久性顯示-1,單位秒、pttl key
以毫秒為單位、切換key從時效性轉換為永久性:persist key
。③查詢key:keys pattern
。查詢模式規則:*
匹配任意數量的任意符號,?
配合一個任意符號,[]
匹配一個指定符號。④為key改名:rename key newkey
、renamenx key newkey
新名不存在時才可使用。
Q10:Redis如何解決key的重複問題?資料庫有哪些基本操作?
答:①redis為每個服務提供有16個資料庫,編號從0到15。每個資料庫之間的資料相互獨立。②切換資料庫:select index
、退出:quit
、測試連通:ping
、輸出資訊:echo message
。③移動到其他資料庫:move key db
、資料個數:dbsize
、清除該資料庫:flushdb
、清除所有資料庫:flushall
。
Q11:Jedis是什麼?
答:①Jedis是一種利用Java語言連線redis的服務,需要依賴redis.clients下的jedis包。②通過new Jedis(String address,int port)建立一個操作redis資料庫的物件,第一個引數是字串類的ip地址,第二個引數是int型別的埠號。③之後通過Jedis類例項物件呼叫相關API實現對redis資料庫的操作。
Q12:新聞網站會出現熱點新聞,熱點新聞最大的特徵是時效性,如何自動控制熱點新聞的時效性?
答:redis 可以控制資料的生命週期,通過資料是否失效控制業務行為,適用於所有具有時效性限定控制的操作,使用String資料結構,通過setex key seconds value
可以設定資料有效的生命週期,有效時間以秒為單位,也可以通過psetex key milliseconds value
設定資料的有效時間,有效時間以毫秒為單位。
Q13:你會如何設計與實現電商網站購物車?
答:①可以使用redis資料庫,以客戶id作為key,每位客戶建立一個hash儲存結構儲存對應的購物車資訊。②將商品編號作為field,購買數量作為value進行儲存。③新增商品:追加全新的field與value。④瀏覽:遍歷hash。⑤更改數量:自增/自減,設定value值。⑥刪除商品:直接刪除field。⑦清空購物車:直接刪除key。⑧當前僅僅是將資料儲存到了redis中,並沒有起到加速的作用,商品資訊還需要二次查詢資料庫,將每條購物車中的商品記錄儲存成兩條field,field1專用於儲存購買數量,命名格式:商品id:nums 數值
;field2專用於儲存購物車中顯示的資訊,包含文字描述,圖片地址,所屬商家資訊等,命名格式:商品id:info json資料
。
Q14:雙11活動日,銷售手機充值卡的商家對移動、聯通、電信的30元、50元、100元商品推出搶購活動,每種商品搶購上限1000張,你會怎麼解決?
答:①使用redis的hash資料結構,以商家id作為key、將參與搶購的商品id作為field、將參與搶購的商品數量作為對應的value。②搶購時使用降值的方式控制產品數量,通過hincrby key field increment
實現對指定key的field值實現值的更新操作,例如hincrby CMCC card30:nums -10
實現對移動的30元商品數量實現-10操作。
Q15:微信朋友圈點贊,要求按照點贊順序顯示點贊好友資訊,如果取消點贊,移除對應好友資訊,你會怎麼實現?
答:redis 可以應用於具有操作先後順序的資料控制,可以使用list資料結構實現,點贊時使用rpush key value
從右新增實現順序顯示功能,取消點贊通過lrem key count value
從list左邊開始移除指定資料。
Q16:每位使用者首次使用今日頭條時會設定3項愛好的內容,但是後期為了增加使用者的活躍度、興趣點,必須讓使用者對其他資訊類別逐漸產生興趣,增加客戶留存度,如何實現?
答:①可以利用redis資料庫的set資料結構完成,系統分析出各個分類的最新或最熱點資訊條目並組織成set集合,隨機挑選其中部分資訊,配合使用者關注資訊分類中的熱點資訊組織成展示的全資訊集合。②通過srandmember key [count]
隨機獲取集合中指定數量的資料,通過spop key [count]
隨機獲取集合中的某個資料並將該資料移出集合。
設計模式 29
Q1:設計模式是什麼?
答:設計模式是經過高度抽象化的在程式設計中可以被反覆使用的程式碼設計經驗的總結。正確使用設計模式能提高程式碼的可讀性、可重用性和可靠性,編寫符合設計模式規範的程式碼不但有利於自身系統的穩定、可靠,還有利於外部系統的對接。在使用了良好設計模式的系統工程中,無論是對滿足當前的需求還是對適應未來的需求,無論是對自身系統間模組的對接還是對外部系統的對接,都有很大幫助。
Q2:設計模式有哪些原則?
答:①單一職責原則:單一職責原則又稱單一功能原則,它規定一個類只有一個職責。如果有多個職責(功能)設計在一個類中,這個類就違反了單一職責原則。②開閉原則:
開閉原則規定軟體中的物件(類、模組、函式等)對擴充套件開放,對修改封閉,這意味著一個實體允許在不改變其原始碼的前提下改變其行為,該特性在產品化的環境下是特別有價值的,在這種環境下,改變原始碼需要經過程式碼審查,單元測試等過程以確保產品的使用質量。遵循這個原則的程式碼在擴充套件時並不發生改變,因此不需要經歷上述過程。③里氏代換原則:里氏代換原則是對開閉原則的補充,規定了在任意父類可以出現的地方,子類都一定可以出現。實現開閉原則的關鍵就是抽象化,父類與子類的繼承關係就是抽象化的具體表現,所以里氏代換原則是對實現抽象化的具體步驟的規範。④依賴倒轉原則:依賴倒轉原則指程式要依賴於抽象(Java中的抽象類和介面),而不依賴於具體的實現(Java中的實現類)。簡單地說,就是要求對抽象進行程式設計,不要求對實現進行程式設計,這就降低了使用者與實現模組之間的耦合度。⑤介面隔離原則:介面隔離原則是指通過將不同的功能定義在不同的介面中來實現介面的隔離,這樣就避免了其他類在依賴該介面(介面上定義的功能)時依賴其不需要的介面,可減少介面之間依賴的冗餘性和複雜性。
⑥合成/聚合複用原則:合成/聚合複用原則指通過在一個新的物件中引入(注入)已有的物件以達到類的功能複用和擴充套件的目的。它的設計原則是要儘量使用合成或聚合而不要使用繼承來擴充套件類的功能。⑦迪米特法則:迪米特法則指一個物件儘可能少地與其他物件發生相互作用,即一個物件對其他物件應該有儘可能少的瞭解或依賴。其核心思想在於降低模組之間的耦合度,提高模組的內聚性。迪米特法則規定每個模組對其它模組都要有儘可能少的瞭解和依賴,因此很容易使系統模組之間的功能獨立,這使得各個模組的獨立執行變得更加簡單,同時使得各個模組之間的組合變得更加容易。
Q3:設計模式有哪些分類?
答:①建立型模式:提供了多種優雅建立物件的方法,包括工廠模式、抽象工廠模式、單例模式、建造者模式、原型模式。②結構型模式:通過類和介面之間的繼承和引用實現建立複雜結構物件的功能,包括介面卡模式、橋接模式、組合模式、裝飾器模式、外觀模式、享元模式、代理模式。③行為型模式:通過類之間不同的通訊方式實現不同的行為方式,包括責任鏈模式、命令模式、直譯器模式、迭代器模式、中介者模式、備忘錄模式、觀察者模式、狀態模式、策略模式、模板模式、訪問者模式。
Q4:簡述工廠模式
答:①工廠模式是最常見的設計模式,該模式屬於建立型模式,它提供了一種簡單、快速、高效而安全地建立物件的方式。②工廠模式在介面中定義了建立物件的方法,而將具體的建立物件的過程在子類中實現,使用者只需通過介面建立需要的物件即可,不用關注物件的具體建立過程。同時,不同的子類可根據需求靈活實現建立物件的不同方法。③通俗地講,工廠模式的本質就是用工廠方法代替new操作建立一種例項化物件的方式,以便提供一種方便地建立有同種型別介面地產品的複雜物件。
Q5:簡述抽象工廠模式
答:①抽象工廠模式在工廠模式上新增了一個建立不同工廠的抽象介面(抽象類或介面實現),該介面可叫做超級工廠。在使用過程中,我們首先通過抽象介面建立出不同的工廠物件,然後根據不同的工廠物件建立不同的物件。②在同一個廠商有多個維度的產品時,如果使用工廠模式,則勢必會存在多個獨立的工廠,這樣的話設計和物理世界是不對應的。正確的做法是通過抽象工廠模式來實現,我們可以將抽象工廠類比成廠商,將通過抽象工廠建立出來的工廠類比成不同產品的生產線,在需要生產產品時根據抽象工廠生產。
Q6:講一講單例模式
答:①單例模式是保證系統例項唯一性的重要手段。單例模式首先通過將類的例項化方法私有化來防止程式通過其他方式建立該類的例項,然後通過提供一個全域性唯一獲取該類例項的方法幫助使用者獲取類的例項,使用者只需也只能通過呼叫該方法獲取類的例項。②單例模式的設計保證了一個類在整個系統中同一時刻只有一個例項存在,主要被用於一個全域性類的物件在多個地方被使用並且物件的狀態是全域性變化的場景下。同時單例模式為系統資源的優化提供了很好的思路,頻繁建立或銷燬物件都會增加系統的資源消耗,而單例模式保障了整個系統只有一個物件能被使用,很好地節約了資源。③單例模式的實現很簡單,每次在獲取物件前都判斷系統是否已經有這個單例物件,有則返回,無則建立。需要注意的是,單例模型的類構造器是私有的,只能由自身建立和銷燬物件,不允許除了該類的其他程式使用new關鍵字建立物件及破壞單例模式。
Q7:懶漢模式執行緒安全嗎?
答:①懶漢模式是執行緒不安全的,在需要時才會建立例項物件。②可以通過加synchronized鎖實現執行緒安全的懶漢模式。③可以在加鎖的基礎上使用volatile關鍵字和雙重校驗鎖進一步提升懶漢模式的執行緒安全性。
Q8:講一講建造者模式
答:①建造者模式使用多個簡單的物件建立一個複雜的物件,用於將一個複雜的構建與其表示分離,使得同樣的構建過程可以建立不同的表示,然後通過一個Builder類(該Builder類是獨立於其他物件的)建立最終的物件。②建造者模式主要用於解決軟體系統中複雜物件的建立問題,比如有些複雜物件的建立需要通過各部分的子物件用一定的演算法構成,在需求變化時這些複雜物件將面臨很大的改變,不利於系統穩定。但是使用建造者模式能將它們各部分的演算法包裝起來,在需求變化後只需調整各個演算法的組合方式和順序,能極大提供系統穩定性。建造者模式常被用於一些基本部件不會變而其組合經常變化的應用場景下。③建造者模式與工廠模式的最大區別是,建造者模式更關注產品的組合方式和裝配順序,而工廠模式關注產品的生產本身。④建造者模式在設計時有以下幾種角色:Builder 建立一個複雜產品物件的抽象介面、ConcreteBuilder Builder介面的實現類,用於定義複雜產品各個部件的裝配流程、Director 構造一個使用Builder介面的物件、Product 表示被構造的複雜物件,ConcreteBuilder定義了該複雜物件的裝配流程,而Product定義了該複雜物件的結構和內部表示。
Q9:講一講原型模式
答:①原型模式指通過呼叫原型例項的Clone方法或其他手段來建立物件。②原型模式屬於建立型設計模式,它以當前物件為原型來建立另一個新的物件,而無需知道建立的細節。原型模式在Java中通常使用Clone技術實現,在JavaScript中通常使用物件的原型屬性實現。原型模式的Java實現很簡單,只需要原型類實現Cloneable介面並重寫clone方法即可。
Q10:淺複製和深複製的區別?
答:Java中的複製分為淺複製和深複製。①淺複製:Java中的淺複製是通過實現Cloneable介面並重寫clone方法實現。在淺複製的過程中,物件的基本資料型別的變數值會重新被複制和建立,而引用資料型別仍指向原物件的引用,也就是說淺複製不復制物件的引用資料型別。②深複製:在深複製的過程中,不論是基本資料型別還是引用資料型別,都會被重新複製和建立。簡而言之,深複製徹底複製了物件的資料,淺複製的複製不徹底(忽略了引用資料型別)。
Q11:講一講介面卡模式
答:①介面卡模式通過定義一個介面卡類作為兩個不相容的介面之間的橋樑,將一個類的介面轉換成使用者期望的另一個介面,使得兩個或多個原本不相容的介面可以基於介面卡類一起工作。②介面卡模式主要通過介面卡類實現各個介面之間的相容,該類通過依賴注入或者繼承實現各個介面的功能並對外統一提供服務。在介面卡模式的實現中有三種角色:source、targetable、adapter。sourc是待適配的類,targetable是目標介面,adapter是介面卡。我們在具體應用中通過adapter將source的功能擴充套件到targetable,以實現介面的相容。介面卡的實現主要分為三類:類介面卡模式、物件介面卡模式、介面介面卡模式。
Q12:講一講裝飾者模式
答:①裝飾者模式指在無需改變原有類及類的繼承關係的情況下,動態擴充套件一個類的功能。它通過裝飾者來包裹真實的物件,並動態地向物件新增或者撤銷功能。②裝飾者模式包括Source和Decorator兩種角色,source是被裝飾者,decorator是裝飾者。裝飾者模式通過裝飾者可以為被裝飾者Source動態地新增一些功能。
Q13:講一講代理模式
答:①代理模式指為物件提供一種通過代理的方式來訪問並控制該物件行為的方法。在客戶端不適合或者不能夠直接引用一個物件時,可以通過該物件的代理物件實現對該物件的訪問,可以將該代理物件理解為客戶端和目標物件之間的中介者。②在代理模式下有兩種角色,一種是被代理者,一種是代理(Proxy),在被代理者需要做一項工作時,不用自己做而是交給代理做。以企業招聘為例,不用自己去市場找,可以通過代理去找。
Q14:講一講外觀模式
答:①外觀模式也叫做門面模式,通過一個門面向客戶端提供一個訪問系統的統一介面,客戶端無需關心和知曉系統內部各子模組(系統)之間的複雜關係,其主要目的是降低訪問擁有多個子系統的複雜系統的難度,簡化客戶端與其之間的介面。外觀模式將子系統中的功能抽象成一個統一的介面,客戶端通過這個介面訪問系統,使得系統使用起來更加容易。②簡單來說外觀模式就是將多個子系統及其之間的複雜關係和呼叫流程封裝到一個統一的介面或類中以對外提供服務,這種模式設計三種角色:子系統角色:實現了子系統的功能;門面角色:外觀模式的核心, 熟悉各子系統的功能和呼叫關係並根據客戶端的需求封裝統一的方法來對外提供服務;客戶角色:通過呼叫門面來完成業務功能。
Q15:講一講橋接模式
答:①橋接模式通過將抽象及其實現解耦,使二者可以根據需求獨立變化。這種型別的設計模式屬於結構型模式,通過定義一個抽象和實現之間的橋接者來達到解耦的目的。②橋接模型主要用於解決在需求多變的情況下使用繼承造成類爆炸的問題,擴充套件起來不夠靈活。可以通過橋接模式將抽象部分與實現部分分離,使其能夠獨立變化而相互之間的功能不受影響。具體的做法是通過定義一個橋接介面,使得實體類的功能獨立於介面實現類,降低他們之間的耦合度。
Q16:你知道哪些應用使用了橋接模式嗎?
答:JDBC和DriverManager就使用了橋接模式,JDBC在連線資料庫時,在各個資料庫之間切換而不需要修改程式碼,因為JDBC提供了統一的介面,每個資料庫都提供了各自的實現,通過一個叫做資料庫驅動的程式來橋接即可。
Q17:講一講組合模式
答:①組合模式又叫做部分整體模式,主要用於實現部分和整體操作的一致性。組合模式常根據樹形結構來表示部分及整體之間的關係,使得使用者對單個物件和組合物件的操作具有一致性。②組合模式通過特定的資料結構簡化了部分和整體之間的關係,使得客戶端可以像處理單個元素一樣來處理整體的資料集,而無需關心單個元素和整體資料集之間的內部複雜結構。
Q18:講一講享元模式
答:①享元模式主要通過物件的複用減少物件建立的次數和數量,減少系統記憶體的使用和降低系統負載。享元模式屬於結構型模型,在系統需要一個物件時享元模式首先在系統中查詢並嘗試重用現有的物件,如果未找到匹配物件則建立新物件並將其快取在系統中。②享元模式主要用於避免在有大量物件時頻繁建立和銷燬物件造成系統資源的浪費,把其中共同的部分抽象出來,如果有相同的業務請求則直接返回記憶體中已有的物件。
Q19:講一講策略模式
答:①策略模式為同一個行為定義了不同策略,為每種策略實現了不同方法。使用者使用時系統根據不同的策略自動切換不同的方法實現策略的改變。同一策略下的不同方法是對同一功能的不同實現,因此在使用時可相互替換而不影響使用者的使用。②策略模式的實現是在介面中定義不同的策略,在實現類中完成了對不同策略下具體行為的實現,並將使用者的策略狀態儲存在上下文中來完成策略的儲存和狀態的改變。
Q20:講一講模板方法模式
答:①模板方法模式定義了一個演算法框架,並通過繼承的方式將演算法的實現延遲到子類中,使得子類可以在不改變演算法框架及其流程的前提下重新定義該演算法在某些特定環節的實現,是一種類行為型模式。②該模式在抽象類中定義了演算法的結構並實現了公共部分演算法,在子類中實現可變的部分並根據不同的業務需求實現不同的擴充套件。模板方法模式的優點在於其父類(抽象類)中定義了演算法的框架以及保障演算法的穩定性,同時在父類中實現了演算法公共部分的方法保證程式碼的複用,將部分演算法延遲到子類實現,因此子類可以通過繼承擴充套件或重新定義演算法的功能而不影響穩定性,符合開閉原則。③抽象類:定義演算法框架,由基本方法和模板方法組成。基本方法定義了演算法有哪些環節,模板方法定義了演算法各個環節執行的流程。具體子類:對在抽象類中定義的演算法根據需求進行不同的實現。
Q21:講一講觀察者模式
答:①觀察者模式指在被觀察者的狀態發生變化時,系統基於事件驅動理論將其狀態通知到訂閱其狀態的觀察者物件中,以完成狀態的修改和事件傳播。觀察者模式是一種物件行為模式,觀察者和被觀察者之間的關係屬於抽象耦合關係,主要優點是觀察者與被觀察者之間建立了一套事件觸發機制,以降低二者之間的耦合度。②觀察者模式的主要角色如下:抽象主題Subject:持有訂閱了該主題的觀察者物件的集合,同時提供了增加刪除觀察者物件的方法和主題狀態變化後的通知方法。具體主題Concrete Subject:實現了抽象主題的通知方法,在主題內部狀態發生變化時,呼叫該方法通知訂閱了主題狀態的觀察者物件。抽象觀察者Observer:觀察者的抽象類或介面,定義了主題狀態變化時需要呼叫的方法。具體觀察者 Concrete Observer:抽象觀察者的實現類,在收到主題狀態變化的資訊後執行具體觸發機制。
Q22:講一講迭代器模式
答:①迭代器模式提供了順序訪問集合物件中的各種元素,而不暴露該物件內部結構的方法。Java中的集合就是典型的迭代器模式,比如HashMap,當遍歷HashMap時,需要迭代器不停地獲取Next元素就可以迴圈遍歷集合中所有元素。②迭代器模式將遍歷集合中所有元素地操作封裝成一個迭代器類,目的是在不暴露集合物件內部結構地情況下,對外提供統一訪問集合內部資料的方法。迭代器的實現一般包括一個迭代器,用於執行具體的遍歷操作,以及一個Collection,用於儲存具體的資料。
Q23:講一講責任鏈模式
答:①責任鏈模式用於避免請求傳送者與多個請求處理者耦合在一起,讓所有請求的處理者持有下一個物件的引用,從而將請求串聯成一條鏈,在有請求發生時,可將請求沿著這條鏈傳遞,直到遇到該物件的處理器。②該模式下使用者只需將請求傳送到責任鏈上即可,無需關心請求的處理細節和傳遞過程,所以責任鏈模式優雅地將請求的傳送和處理進行了解耦。責任鏈模式常用於Web模式。③責任鏈模式包含以下三種角色:Handler介面:規定責任鏈上要執行的具體方法。AbstractHandler抽象類:持有Handler例項並通過get/set方法將各個具體的業務Handler串聯成一個責任鏈,客戶端上的請求在責任鏈上執行。業務Handler:使用者根據具體的業務需求實現的業務邏輯。
Q24:講一講命令模式
答:①命令模式將請求封裝為命令基於事件驅動非同步執行,以實現命令的傳送者和命令的執行者之間的解耦,提高命令傳送執行的效率和靈活度。②命令模式主要包含以下角色:
抽象命令類:執行命令的介面,定義執行命令的抽象方法。具體命令類:抽象命令類的實現類,持有接收者物件,並在收到命令後呼叫命令執行者的方法action()實現命令的呼叫和執行。命令執行者:命令的具體執行者,定義了命令執行的具體方法action()。命令呼叫者:接收客戶端的命令並非同步執行。
Q25:講一講備忘錄模式
答:①備忘錄模式又叫做快照模式,該模式將當前物件的內部狀態儲存到備忘錄中,以便在需要時能將物件的狀態恢復到原先儲存的狀態。備忘錄模式提供了一種儲存和恢復狀態的機制,常用於快照的記錄和狀態的儲存,在系統發生鼓掌或資料發生不一致時能夠方便地將資料恢復到某個歷史狀態。②備忘錄的核心是設計備忘錄類及用於管理備忘錄的管理者類,主要角色如下:發起人Originator:記錄當前時刻的內部狀態,定義建立備忘錄和回覆備忘錄資料的方法。備忘錄Memento:負責儲存物件的內部狀態。狀態管理者Storage:對備忘錄的歷史狀態進行儲存,定義了儲存和獲取備忘錄狀態的功能。注意備忘錄只能被儲存或恢復,不能進行修改。
Q26:講一講狀態模式
答:①狀態模式指給物件定義不同的狀態,併為不同的狀態定義不同的行為,在物件的狀態發生變換時自動切換狀態的行為。狀態模式是一種物件行為型模式,它將物件的不同行為封裝到不同的狀態中,遵循單一職責原則。②具體角色如下:環境: 也叫做上下文,用於維護物件當前的狀態,並在物件狀態發生變化時觸發物件行為的變化。抽象狀態:定義介面,用於定義物件中不同狀態對應行為。具體狀態:抽象狀態的實現類
Q27:講一講訪問者模式
答:①訪問者模式指將資料結構和資料的操作分離開來,使其在不改變資料結構的前提下動態新增作用於這些元素的操作。訪問者模式通過定義不同的訪問者實現對資料的不同操作,因此在需要給資料新增新的操作時只需為其定義一個新的訪問者即可。②訪問者模式是一種物件行為型模式,主要特點是將資料結構和作用於結構上的操作解耦,使得集合的操作可自由地演化而不影響其資料結構,它適用於資料結構穩定但操作多變的系統中。③主要角色如下:抽象訪問者:定義了一個訪問元素的介面,為每類元素都定義了一個訪問操作,該操作中的引數型別對應被訪問元素的資料型別。具體訪問者:抽象訪問者的實現類,實現了不同訪問者訪問元素後具體行為。抽象元素:定義了訪問該元素的入口方法,不同訪問者型別代表不同訪問者。具體元素:實現抽象元素定義的入口方法,根據訪問者的不同型別實現不同邏輯業務。
Q28:講一講中介者模式
答:①中介者模式指物件和物件之間不直接互動,而是通過一個名為中介者的角色來實現,使原有物件之間的關係變得鬆散,且可以通過定義不同的中介者來改變它們之間的互動。②主要包含以下角色:抽象中介者:中介者介面,定義了註冊同事物件方法和轉發同時物件資訊的方法。具體中介者:中介者介面的實現類,定義了一個集合儲存同事物件,協調各同事角色之間的互動關係。抽象同事類:定義同事的介面類,持有中介者物件,並定義同事物件互動的抽象方法,同時實現同事類的公共方法和功能。具體同事類:抽象同事的實現類,在需要與其他同事物件互動時,通過中介者物件來完成。
Q29:講一講直譯器模式
答:①直譯器模式給定一種語言,並定義該語言的語法表示,然後設計一個直譯器來解釋語言的語法,這種模式常被用於SQL解析、符號處理引擎等。②直譯器模式包含以下主要角色:抽象表示式:定義直譯器的介面,約定直譯器所包含的操作。終結符表示式:抽象表示式的子類,用來定義語法中和終結符有關的操作,語法中的每一個終結符都應有一個與之對應的終結表示式。非終結符表示式:抽象表示式的子類,用來定義語法中和非終結符有關的操作,語法中的每條規則都有一個非終結符表示式與之對應。環境:定義各個直譯器需要的共享資料或公共功能。
計算機網路 7
Q1:說一說OSI網路模型
答:網路的七層架構從下到上主要包括物理層、資料鏈路層、網路層、傳輸層、會話層、表示層和應用層。①物理層:物理層主要定義物理裝置標準,主要作用是傳輸位元流,具體做法是在傳送端將1、0轉化為電流強弱來進行傳輸,在到達目的地之後再將電流強弱轉化為1、0,也就是我們常說的模數轉換與數模轉換,這一層的資料叫做位元。②資料鏈路層:資料鏈路層主要用於對資料包中的MAC地址進行解析和封裝。這一層的資料叫做幀,在這一層工作的裝置是網路卡、網橋、交換機。③網路層:網路層主要用於對資料包中的IP地址進行封裝和解析,這一層的資料叫做資料包。在這一層工作的裝置有路由器、交換機、防火牆等。④傳輸層:傳輸層定義了傳輸資料的協議和埠號,主要用於資料的分段、傳輸和重組。在這一層工作的協議有TCP和UDP等。TCP是傳輸控制協議,傳輸效率低,可靠性強,用於傳輸對可靠性要求高,資料量大的資料,比如支付寶轉賬業務;UDP是使用者資料包協議,用於傳輸可靠性要求不高,資料量小的資料,例如抖音等視訊服務。⑤會話層:會話層在傳輸層的基礎上建立連線和管理會話,具體包括登陸驗證、斷點續傳、資料粘包與分包等。在裝置之間需要互相識別的可以是IP,也可以是MAC或者主機名。⑥表示層:表示層主要對接收的資料進行解釋、加密、解密、壓縮、解壓縮等,即把計算機能夠識別的內容轉換成人能夠識別的內容(圖片、聲音、文字等)。⑦應用層:基於網路構建具體應用,例如FTP上傳檔案下載服務、Telnet服務、HTTP服務、DNS服務、SNMP郵件服務等。
Q2:說一說TCP/IP的網路模型
答:TCP/IP不是指TCP和IP這兩個協議的合稱,而是指因特網的整個TCP/IP協議簇。從協議分層模型方面來講,TCP/IP由4個層次組成:網路介面層、網路層、傳輸層和應用層。①網路介面層:定義了主機間網路連通的協議,具體包括Echernet、FDDI、ATM等通訊協議。②網路層:主要用於資料的傳輸、路由及地址的解析,以保障主機可以把資料傳送給任何網路上的目標。資料經過網路傳輸,傳送的順序和到達的順序可能發生變化。在網路層使用IP協議和ARP地址解析協議。③傳輸層:使源端和目的端的機器上的對等實體可以基於會話相互通訊。在這一層定義了兩個端到端的協議TCP和UDP。TCP是面向連線的協議,提供可靠的報文傳輸和對上層應用的連線服務,除了基本的資料傳輸,它還有可靠性保證、流量控制、多路複用、優先權和安全性控制等功能。UDP是面向無連線的不可靠傳輸的協議,主要用於不需要TCP的排序和流量控制等功能的應用程式。④應用層:負責具體應用層協議的定義,包括Telnet虛擬終端協議、FTP檔案傳輸協議、SMTP簡單電子郵件傳輸協議、DNS域名解析服務、NNTP網上新聞傳輸協議和HTTP超文字傳輸協議等。
Q3:簡述TCP的三次握手過程,為什麼不是兩次或四次?
答:①服務端建立傳輸控制塊TCB,進入LISTEN狀態,準備接收客戶端的請求。客戶端同樣先建立TCB,然後當準備建立連線時向服務端傳送連線請求報文(SYN=1,seq=x),然後進入SYN-SENT狀態。②服務端收到後向客戶端傳送確認報文(SYN=1,ACK=1,ack=x+1,seq=y),進入SYN-RCVD狀態。③客戶端接收到確認後,再向服務端傳送一個確認報文(ACK=1,ack=y+1,seq=x+1),然後進入ESTABLISHED狀態,服務端接收後也進入ESTABLISHED狀態。
④不是兩次的原因是為了避免無效的連線請求突然傳送到服務端,而此時客戶端已關閉,服務端誤以為客戶端將要傳送資料會白白浪費資源。⑤不是四次的原因是將服務端的SYN和ACK報文拆分成兩次傳送和一次的效果是相同的,沒有意義。
Q4:簡述TCP的四次握手過程,為什麼不是三次?
答:①當客戶端準備關閉連線時,向服務端傳送連線終止報文(FIN=1,seq=u),進入FIN-WAIT-1狀態。②服務端接收後向客戶端傳送確認報文(ACK=1,ack=u+1,seq=v),進入CLOSE-WAIT狀態,客戶端收到後進入FIN-WAIT-2狀態,此時TCP連線處於半關閉狀態。③當服務端也傳送完全部資料準備斷開連線時,向客戶傳送連線終止報文(FIN=1,ACK=1,ack=u+1,seq=w),進入LAST-ACK狀態。④客戶端接收到該報文後,傳送一個確認報文(ACK=w+1,ack=1,seq=u+1),進入TIME-WAIT狀態,然後等待2MSL時間後關閉。服務端收到後關閉,時間將略早於客戶端。⑤不是三次的原因第一是為了保證客戶端傳送的最後一個報文可以到達服務端,如果該報文丟失那麼服務端會超時重傳之前的FIN+ACK報文,客戶端可以在2MSL內收到,第二是防止已失效的報文傳送到客戶端,在2MSL後客戶端在本連線時間內發出的所有報文都將從網路中消失。
Q5:簡述HTTP的傳輸流程
答:①地址解析:地址解析通過域名系統DNS解析伺服器域名從而獲得主機的IP地址。例如客戶端的瀏覽器請求http://localhost:8080/index.html,則可分析出:協議名HTTP、主機名localhost、埠8080、物件路徑/index.html。②封裝HTTP資料包:解析協議名、主機名、埠、物件路徑等並結合本機自己的資訊封裝成一個HTTP請求資料包。③封裝TCP包:將HTTP請求資料包進一步封裝成TCP資料包。④建立TCP連線:基於TCP的三次握手機制建立TCP連線。⑤客戶端傳送請求:在建立連線後,客戶端傳送一個請求給伺服器。⑥伺服器響應:伺服器在接收到請求後,結合業務邏輯進行資料處理,然後向客戶端返回相應的響應資訊。在響應資訊中包含狀態行、協議版本號、成功或錯誤的程式碼、訊息體等內容。⑦伺服器關閉TCP連線:伺服器在向瀏覽器傳送請求響應資料後關閉TCP連線。但如果瀏覽器或者伺服器在訊息頭加入了Connection:keep-alive,則TCP連線在請求響應資料後仍然保持連線狀態,在下一次請求中瀏覽器可以繼續使用相同的連線傳送請求。採用keep-alive不但減少了請求響應的時間,還節約了網路頻寬和系統資源。
Q6:HTTPS是什麼?
答:HTTPS是以安全為目標的HTTP通道,它在HTTP中加入SSL層以提高資料傳輸的安全性。HTTP被用於在Web瀏覽器和網站伺服器之間傳遞資訊,但以明文方式傳送內容,不提供任何方式的資料加密,如果攻擊者擷取了Web瀏覽器和網站伺服器之間的傳輸報文,就可以直接讀懂其中的資訊,因此HTTP不適合傳輸一些敏感資訊,比如身份證號碼、密碼等。為了資料傳輸的安全,HTTPS在HTTP的基礎上加入了SSL協議,SSL依靠證照來驗證伺服器的身份,並對瀏覽器和伺服器之間的通訊進行資料加密,以保障資料傳輸的安全性,其埠一般是443
。
Q7:簡述HTTPS的加密流程
答:①發起請求:客戶端在通過TCP和伺服器建立連線之後(443埠),發出一個請求證照的訊息給伺服器,在該請求訊息裡包含自己可實現的演算法列表和其他需要的訊息。②證照返回:服務端在收到訊息後回應客戶端並返回證照,在證照中包含伺服器資訊、域名、申請證照的公司、公鑰、資料加密演算法等。③證照驗證:客戶端在收到證照後,判斷證照籤發機構是否正確,並使用該簽發機構的公鑰確認簽名是否有效,客戶端還會確認在證照中列出的域名就是它正在連線的域名。如果客戶端確認證照有效,則生成對稱金鑰,並使用公鑰將對稱金鑰加密。④金鑰交換:客戶端將加密後的對稱金鑰傳送給伺服器,伺服器在接收到對稱金鑰後使用私鑰解密。⑤資料傳輸:經過上述步驟,客戶端和伺服器就完成了金鑰對的交換,在之後的資料傳輸過程中,客戶端和服務端就可以基於對稱加密(加密和解密使用相同金鑰的加密演算法)對資料加密後在網路上傳輸,保證了網路資料傳輸的安全性。
作業系統 2
Q1:程式和執行緒有什麼區別?
答:①程式是一個具有獨立功能的程式關於某個資料集合的一次執行活動,是系統進行資源分配和排程的一個獨立單位。②執行緒是一種輕量級的程式,是一個基本的CPU執行單元也是程式執行流的最小單元。執行緒是程式中的一個實體,是被系統獨立排程和分配的基本單位,執行緒不擁有系統資源,只擁有一點執行必備的資源,但可與其他同屬一個程式的執行緒共享程式擁有的全部資源。③引入程式的目的是為了更好地使多道程式併發執行,提高系統資源利用率和吞吐量,增加併發程度。引入執行緒地目的使為了減小程式在併發執行時的開銷,提高系統的併發能力。④堆是執行緒共享的,棧是執行緒私有的。
Q2:死鎖產生的原因和解決方法?
答:①死鎖是多個程式競爭共享資源而造成互相等待的僵局,若無外力作用這些程式都將無法向前推進。②死鎖產生的原因是非剝奪資源的競爭和程式的不恰當推進順序。③預防死鎖:破壞互斥條件、破壞不剝奪條件、破壞請求和保持條件、破壞迴圈等待條件。④預防死鎖:安全狀態:能找到一個分配資源的序列讓所有程式都順序完成。銀行家演算法:採用預分配策略檢查分配完成時系統是否處於安全狀態。⑤檢測死鎖:利用死鎖定理化簡資源分配圖檢測死鎖的存在。⑥解除死鎖:資源剝奪法:掛起某些死鎖程式並搶奪它的資源,以便其他執行緒繼續推進。撤銷程式法:強制撤銷部分、甚至全部程式並搶奪其資源,以便讓其他程式繼續推進。程式回退法:讓一個或多個程式回退到足以避免死鎖的地步。
相關文章
- 2020Java實習必看面試兩百題解析 (下)Java面試
- 前端面試題乾貨集合前端面試題
- 今日頭條實習面試題解析面試題
- 實用乾貨!P6級Java面試題歸總Java面試題
- 技術乾貨:RabbitMQ面試題及答案MQ面試題
- 技術乾貨:ActiveMQ面試題及答案MQ面試題
- 乾貨分享:18道Spring面試題Spring面試題
- Java面試題-基礎篇三(乾貨)Java面試題
- 百度搜尋 “Java面試題” 前200頁(面試必看)Java面試題
- RabbitMQ面試專題,面試必看MQ面試
- 技術乾貨:Hadoop面試題及答案Hadoop面試題
- 「乾貨」22道機器學習常見面試題目機器學習面試題
- [乾貨] 位運算面試題大總結面試題
- 程式設計師面試備戰篇:18個經典MySQL面試專題解析(乾貨分享答案)程式設計師面試MySql
- 技術乾貨:spring boot面試題及答案Spring Boot面試題
- 斬獲BAT-offer大神的兩萬字面試乾貨分享BAT面試
- 技術乾貨:Tomcat面試題彙總及答案Tomcat面試題
- 技術乾貨:Kotlin面試題彙總及答案Kotlin面試題
- 乾貨來臨:C語言面試54題附答案C語言面試
- defer問題——面試Go必看面試Go
- Java面試必看二十問題Java面試
- 【機器學習】機器學習面試乾貨精講機器學習面試
- 【乾貨】BAT面試經驗分享BAT面試
- Java開發基礎常見面試題及答案彙總(實用乾貨!)Java面試題
- 技術乾貨:spring cloud面試題彙總及答案SpringCloud面試題
- 技術乾貨:Kubernetes面試題彙總及答案面試題
- 技術乾貨:關於效能測試面試題及答案面試題
- 技術乾貨:ASP.net mvc面試32題附答案ASP.NETMVC面試
- 乾貨 | BAT等一線大廠 Elasticsearch面試題解讀BATElasticsearch面試題
- java面試題-大學畢業必看Java面試題
- 資料庫面試題(開發者必看)資料庫面試題
- java面試題大合集(開發者必看)Java面試題
- Android拿高薪面試題必看Android高薪面試題
- 乾貨:HashMap的工作原理解析HashMap
- 乾貨:ANR日誌分析全面解析
- ES6面試、複習乾貨知識點彙總(全)面試
- 純乾貨!面試官如何面試程式設計師面試程式設計師
- Python面試50題!面試鞏固必看!【轉】Python面試