互联网高级面试题目
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
Java 基礎知識
面向?qū)ο蟮奶匦杂心男?#xff1f;
封裝、繼承和多態(tài)。
Java 中覆蓋和重載是什么意思?
覆蓋(Override)是指子類對父類方法的一種重寫,只能比父類拋出更少的異常,訪問權限不能比父類的小。
被覆蓋的方法不能是 private 的,否則只是在子類中重新定義了一個方法;重載(Overload)表示同一個類中可以有多個名稱相同的方法,但這些方法的參數(shù)列表各不相同。
那么構成重載的條件有哪些?
參數(shù)類型不同、參數(shù)個數(shù)不同、參數(shù)順序不同。
函數(shù)的返回值不同可以構成重載嗎?為什么?
不可以,因為 Java 中調(diào)用函數(shù)并不需要強制賦值。舉例如下:
如下兩個方法:
void f(){} int f(){ return 1;}
只要編譯器可以根據(jù)語境明確判斷出語義,比如在 int x = f();中,那么的確可以據(jù)此區(qū)分重載方法。
不過, 有時你并不關心方法的返回值,你想要的是方法調(diào)用的其他效果?(這常被稱為 “為了副作用而調(diào)用”),這時你可能會調(diào)用方法而忽略其返回值,所以如果像下面的調(diào)用:
fun();
此時 Java 如何才能判斷調(diào)用的是哪一個 f( ) 呢?別人如何理解這種代碼呢?所以,根據(jù)方法返回值來區(qū)分重載方法是行不通的。
抽象類和接口的區(qū)別有哪些?
抽象類中可以沒有抽象方法;接口中的方法必須是抽象方法;
抽象類中可以有普通的成員變量;接口中的變量必須是 static final 類型的,必須被初始化 , 接口中只有常量,沒有變量。
抽象類只能單繼承,接口可以繼承多個父接口;
Java8 中接口中會有 default 方法,即方法可以被實現(xiàn)
? ?抽象類和接口如何選擇?
如果要創(chuàng)建不帶任何方法定義和成員變量的基類,那么就應該選擇接口而不是抽象類。
如果知道某個類應該是基類,那么第一個選擇的應該是讓它成為一個接口,只有在必須要有方法定義和成員變量的時候,才應該選擇抽象類。
因為抽象類中允許存在一個或多個被具體實現(xiàn)的方法,只要方法沒有被全部實現(xiàn)該類就仍是抽象類。
Java 和 C++ 的區(qū)別:
都是面向?qū)ο蟮恼Z言,都支持封裝、繼承和多態(tài);
指針:Java 不提供指針來直接訪問內(nèi)存,程序更加安全;
繼承:?Java 的類是單繼承的,C++ 支持多重繼承; Java 通過一個類實現(xiàn)多個接口來實現(xiàn) C++ 中的多重繼承; Java 中類不可以多繼承,但是!!!接口可以多繼承;
內(nèi)存:?Java 有自動內(nèi)存管理機制,不需要程序員手動釋放無用內(nèi)存
Java 中的值傳遞和引用傳遞
值傳遞是指對象被值傳遞,意味著傳遞了對象的一個副本,即使副本被改變,也不會影響源對象。引用傳遞是指對象被引用傳遞,意味著傳遞的并不是實際的對象,而是對象的引用。
因此,外部對引用對象的改變會反映到所有的對象上。
JDK 中常用的包有哪些?
java.lang、java.util、java.io、java.net、java.sql。
JDK,JRE 和 JVM 的聯(lián)系和區(qū)別:
JDK?是 java 開發(fā)工具包,是 java 開發(fā)環(huán)境的核心組件,并提供編譯、調(diào)試和運行一個 java 程序所需要的所有工具,可執(zhí)行文件和二進制文件,是一個平臺特定的軟件。
JRE?是 java 運行時環(huán)境,是 JVM 的實施實現(xiàn),提供了運行 java 程序的平臺。JRE 包含了 JVM,但是不包含 java 編譯器 / 調(diào)試器之類的開發(fā)工具。
JVM?是 java 虛擬機,當我們運行一個程序時,JVM 負責將字節(jié)碼轉(zhuǎn)換為特定機器代碼,JVM 提供了內(nèi)存管理 / 垃圾回收和安全機制等
這種獨立于硬件和操作系統(tǒng),正是 java 程序可以一次編寫多處執(zhí)行的原因。
區(qū)別:
JDK 用于開發(fā),JRE 用于運行 java 程序;
JDK 和 JRE 中都包含 JVM;
JVM 是 java 編程語言的核心并且具有平臺獨立性。
Java 中常見集合
說說常見的集合有哪些吧
Map 接口和 Collection 接口是所有集合框架的父接口:
1. Collection 接口的子接口包括:Set 接口和 List 接口;
2. Map 接口的實現(xiàn)類主要有:HashMap、TreeMap、Hashtable、ConcurrentHashMap 以及 Properties 等;
3. Set 接口的實現(xiàn)類主要有:HashSet、TreeSet、LinkedHashSet 等;
4. List 接口的實現(xiàn)類主要有:ArrayList、LinkedList、Stack 以及 Vector 等
?HashMap 和 Hashtable 的區(qū)別有哪些?(必問)
HashMap 沒有考慮同步,是線程不安全的;Hashtable 使用了 synchronized 關鍵字,是線程安全的;
前者允許 null 作為 Key;后者不允許 null 作為 Key。
?HashMap 的底層實現(xiàn)你知道嗎?
在 Java8 之前,其底層實現(xiàn)是數(shù)組 + 鏈表實現(xiàn),Java8 使用了數(shù)組 + 鏈表 + 紅黑樹實現(xiàn)。此時你可以簡單的在紙上畫圖分析:
ConcurrentHashMap 和 Hashtable 的區(qū)別?
ConcurrentHashMap 結合了 HashMap 和 HashTable 二者的優(yōu)勢。
HashMap 沒有考慮同步,hashtable 考慮了同步的問題。但是 hashtable 在每次同步執(zhí)行時都要鎖住整個結構。
ConcurrentHashMap 鎖的方式是稍微細粒度的。 ConcurrentHashMap 將 hash 表分為 16 個桶(默認值),諸如 get,put,remove 等常用操作只鎖當前需要用到的桶
ConcurrentHashMap 的具體實現(xiàn)知道嗎?
該類包含兩個靜態(tài)內(nèi)部類 HashEntry 和 Segment;前者用來封裝映射表的鍵值對,后者用來充當鎖的角色;
Segment 是一種可重入的鎖 ReentrantLock,每個 Segment 守護一個 HashEntry 數(shù)組里得元素,當對 HashEntry 數(shù)組的數(shù)據(jù)進行修改時,必須首先獲得對應的 Segment 鎖。
HashMap 的長度為什么是 2 的冪次方?
通過將 Key 的 hash 值與 length-1 進行 & 運算,實現(xiàn)了當前 Key 的定位,2 的冪次方可以減少沖突(碰撞)的次數(shù),提高 HashMap 查詢效率;
如果 length 為 2 的次冪 ?則 length-1 轉(zhuǎn)化為二進制必定是 11111……的形式,在于 h 的二進制與操作效率會非常的快,而且空間不浪費;
如果 length 不是 2 的次冪,比如 length 為 15,則 length-1 為 14,對應的二進制為 1110,在于 h 與操作,最后一位都為 0,而 0001,0011,0101,1001,1011,0111,1101 這幾個位置永遠都不能存放元素了,空間浪費相當大。
更糟的是這種情況中,數(shù)組可以使用的位置比數(shù)組長度小了很多,這意味著進一步增加了碰撞的幾率,減慢了查詢的效率!這樣就會造成空間的浪費。
List 和 Set 的區(qū)別是啥?
List 元素是有序的,可以重復;Set 元素是無序的,不可以重復。
List、Set 和 Map 的初始容量和加載因子
1. List
-
ArrayList 的初始容量是 10;加載因子為 0.5; 擴容增量:原容量的 0.5 倍 +1;一次擴容后長度為 16。
-
Vector 初始容量為 10,加載因子是 1。擴容增量:原容量的 1 倍,如 Vector 的容量為 10,一次擴容后是容量為 20。
2. Set
HashSet,初始容量為 16,加載因子為 0.75; 擴容增量:原容量的 1 倍; 如 HashSet 的容量為 16,一次擴容后容量為 32
3. Map
HashMap,初始容量 16,加載因子為 0.75; 擴容增量:原容量的 1 倍; 如 HashMap 的容量為 16,一次擴容后容量為 32
?Comparable 接口和 Comparator 接口有什么區(qū)別?
前者簡單,但是如果需要重新定義比較類型時,需要修改源代碼。
后者不需要修改源代碼,自定義一個比較器,實現(xiàn)自定義的比較方法。
Java 集合的快速失敗機制 “fail-fast”
它是 java 集合的一種錯誤檢測機制,當多個線程對集合進行結構上的改變的操作時,有可能會產(chǎn)生 fail-fast 機制。
例如 :假設存在兩個線程(線程 1、線程 2),線程 1 通過 Iterator 在遍歷集合 A 中的元素,在某個時候線程 2 修改了集合 A 的結構(是結構上面的修改,而不是簡單的修改集合元素的內(nèi)容),那么這個時候程序就會拋出 ConcurrentModificationException 異常,從而產(chǎn)生 fail-fast 機制。
原因:?迭代器在遍歷時直接訪問集合中的內(nèi)容,并且在遍歷過程中使用一個 modCount 變量。集合在被遍歷期間如果內(nèi)容發(fā)生變化,就會改變 modCount 的值。
每當?shù)魇褂?hashNext()/next() 遍歷下一個元素之前,都會檢測 modCount 變量是否為 expectedmodCount 值,是的話就返回遍歷;否則拋出異常,終止遍歷。
解決辦法:
在遍歷過程中,所有涉及到改變 modCount 值得地方全部加上 synchronized;
使用 CopyOnWriteArrayList 來替換 ArrayList
高并發(fā)編程
01. 多線程和單線程的區(qū)別和聯(lián)系:
答:
在單核 CPU 中,將 CPU 分為很小的時間片,在每一時刻只能有一個線程在執(zhí)行,是一種微觀上輪流占用 CPU 的機制。
多線程會存在線程上下文切換,會導致程序執(zhí)行速度變慢,即采用一個擁有兩個線程的進程執(zhí)行所需要的時間比一個線程的進程執(zhí)行兩次所需要的時間要多一些。
結論:即采用多線程不會提高程序的執(zhí)行速度,反而會降低速度,但是對于用戶來說,可以減少用戶的響應時間。
02. 如何指定多個線程的執(zhí)行順序?
解析:面試官會給你舉個例子,如何讓 10 個線程按照順序打印 0123456789?(寫代碼實現(xiàn))
答:
設定一個 orderNum,每個線程執(zhí)行結束之后,更新 orderNum,指明下一個要執(zhí)行的線程。并且喚醒所有的等待線程。
在每一個線程的開始,要 while 判斷 orderNum 是否等于自己的要求值!!不是,則 wait,是則執(zhí)行本線程。
03. 線程和進程的區(qū)別(必考)
答:
進程是一個 “執(zhí)行中的程序”,是系統(tǒng)進行資源分配和調(diào)度的一個獨立單位;
線程是進程的一個實體,一個進程中擁有多個線程,線程之間共享地址空間和其它資源(所以通信和同步等操作線程比進程更加容易);
線程上下文的切換比進程上下文切換要快很多。
-
(1)進程切換時,涉及到當前進程的 CPU 環(huán)境的保存和新被調(diào)度運行進程的 CPU 環(huán)境的設置。
-
(2)線程切換僅需要保存和設置少量的寄存器內(nèi)容,不涉及存儲管理方面的操作。
04. 多線程產(chǎn)生死鎖的 4 個必要條件?
答:
互斥條件:一個資源每次只能被一個線程使用;
請求與保持條件:一個線程因請求資源而阻塞時,對已獲得的資源保持不放;
不剝奪條件:進程已經(jīng)獲得的資源,在未使用完之前,不能強行剝奪;
循環(huán)等待條件:若干線程之間形成一種頭尾相接的循環(huán)等待資源關系。
面試官:如何避免死鎖?(經(jīng)常接著問這個問題哦~)
答:指定獲取鎖的順序,舉例如下:
比如某個線程只有獲得 A 鎖和 B 鎖才能對某資源進行操作,在多線程條件下,如何避免死鎖?
獲得鎖的順序是一定的,比如規(guī)定,只有獲得 A 鎖的線程才有資格獲取 B 鎖,按順序獲取鎖就可以避免死鎖!!!
05. sleep( ) 和 wait( n)、wait( ) 的區(qū)別:
答:
sleep 方法:是 Thread 類的靜態(tài)方法,當前線程將睡眠 n 毫秒,線程進入阻塞狀態(tài)。當睡眠時間到了,會解除阻塞,進行可運行狀態(tài),等待 CPU 的到來。睡眠不釋放鎖(如果有的話);
wait 方法:是 Object 的方法,必須與 synchronized 關鍵字一起使用,線程進入阻塞狀態(tài),當 notify 或者 notifyall 被調(diào)用后,會解除阻塞。但是,只有重新占用互斥鎖之后才會進入可運行狀態(tài)。睡眠時,釋放互斥鎖。
06. synchronized 關鍵字:
答:
底層實現(xiàn):
進入時,執(zhí)行 monitorenter,將計數(shù)器 +1,釋放鎖 monitorexit 時,計數(shù)器-1;
當一個線程判斷到計數(shù)器為 0 時,則當前鎖空閑,可以占用;反之,當前線程進入等待狀態(tài)。
含義:(monitor 機制)
Synchronized 是在加鎖,加對象鎖。對象鎖是一種重量鎖(monitor),synchronized 的鎖機制會根據(jù)線程競爭情況在運行時會有偏向鎖(單一線程)、輕量鎖(多個線程訪問 synchronized 區(qū)域)、對象鎖(重量鎖,多個線程存在競爭的情況)、自旋鎖等。
該關鍵字是一個幾種鎖的封裝。
07. volatile 關鍵字
解析:關于指令重排序的問題,可以查閱 DCL 雙檢鎖失效相關資料。
答:
該關鍵字可以保證可見性不保證原子性。
功能:
主內(nèi)存和工作內(nèi)存,直接與主內(nèi)存產(chǎn)生交互,進行讀寫操作,保證可見性;
禁止 JVM 進行的指令重排序。
08. ThreadLocal(線程局部變量)關鍵字:
答:
當使用 ThreadLocal 維護變量時,其為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立的改變自己的副本,而不會影響其他線程對應的副本。
ThreadLocal 內(nèi)部實現(xiàn)機制:
每個線程內(nèi)部都會維護一個類似 HashMap 的對象,稱為 ThreadLocalMap,里邊會包含若干了 Entry(K-V 鍵值對),相應的線程被稱為這些 Entry 的屬主線程;
Entry 的 Key 是一個 ThreadLocal 實例,Value 是一個線程特有對象。Entry 的作用即是:為其屬主線程建立起一個 ThreadLocal 實例與一個線程特有對象之間的對應關系;
Entry 對 Key 的引用是弱引用;Entry 對 Value 的引用是強引用。
09. Atomic 關鍵字:
答:可以使基本數(shù)據(jù)類型以原子的方式實現(xiàn)自增自減等操作。
10. 線程池有了解嗎?(必考)
答:
java.util.concurrent.ThreadPoolExecutor 類就是一個線程池。客戶端調(diào)用 ThreadPoolExecutor.submit(Runnable task) 提交任務,線程池內(nèi)部維護的工作者線程的數(shù)量就是該線程池的線程池大小,有 3 種形態(tài):
-
當前線程池大小 :表示線程池中實際工作者線程的數(shù)量;
-
最大線程池大小 (maxinumPoolSize):表示線程池中允許存在的工作者線程的數(shù)量上限;
-
核心線程大小 (corePoolSize ):表示一個不大于最大線程池大小的工作者線程數(shù)量上限。
如果運行的線程少于 corePoolSize,則 Executor 始終首選添加新的線程,而不進行排隊;
如果運行的線程等于或者多于 corePoolSize,則 Executor 始終首選將請求加入隊列,而不是添加新線程;
如果無法將請求加入隊列,即隊列已經(jīng)滿了,則創(chuàng)建新的線程,除非創(chuàng)建此線程超出 maxinumPoolSize, 在這種情況下,任務將被拒絕。
JVM 內(nèi)存管理
01. JVM 內(nèi)存劃分:
方法區(qū)(線程共享):常量、靜態(tài)變量、JIT(即時編譯器) 編譯后的代碼也都在方法區(qū);
堆內(nèi)存(線程共享):垃圾回收的主要場所;
程序計數(shù)器: 當前線程執(zhí)行的字節(jié)碼的位置指示器;
虛擬機棧(棧內(nèi)存):保存局部變量、基本數(shù)據(jù)類型變量以及堆內(nèi)存中某個對象的引用變量;
本地方法棧 :為 JVM 提供使用 native 方法的服務。
02. 類似-Xms、-Xmn 這些參數(shù)的含義:
答:
堆內(nèi)存分配:
JVM 初始分配的內(nèi)存由-Xms 指定,默認是物理內(nèi)存的 1/64;
JVM 最大分配的內(nèi)存由-Xmx 指定,默認是物理內(nèi)存的 1/4;
默認空余堆內(nèi)存小于 40% 時,JVM 就會增大堆直到-Xmx 的最大限制;空余堆內(nèi)存大于 70% 時,JVM 會減少堆直到 -Xms 的最小限制;
因此服務器一般設置-Xms、-Xmx 相等以避免在每次 GC 后調(diào)整堆的大小。對象的堆內(nèi)存由稱為垃圾回收器的自動內(nèi)存管理系統(tǒng)回收。
非堆內(nèi)存分配:
JVM 使用-XX:PermSize 設置非堆內(nèi)存初始值,默認是物理內(nèi)存的 1/64;
由 XX:MaxPermSize 設置最大非堆內(nèi)存的大小,默認是物理內(nèi)存的 1/4;
-Xmn2G:設置年輕代大小為 2G;
-XX:SurvivorRatio,設置年輕代中 Eden 區(qū)與 Survivor 區(qū)的比值。
03. 垃圾回收算法有哪些?
答:
引用計數(shù) :原理是此對象有一個引用,即增加一個計數(shù),刪除一個引用則減少一個計數(shù)。垃圾回收時,只用收集計數(shù)為 0 的對象。此算法最致命的是無法處理循環(huán)引用的問題;
標記-清除 :此算法執(zhí)行分兩階段。第一階段從引用根節(jié)點開始標記所有被引用的對象,第二階段遍歷整個堆,把未標記的對象清除;
此算法需要暫停整個應用,同時,會產(chǎn)生內(nèi)存碎片;
復制算法 :此算法把內(nèi)存空間劃為兩個相等的區(qū)域,每次只使用其中一個區(qū)域。垃圾回收時,遍歷當前使用區(qū)域,把正在使用中的對象復制到另外一個區(qū)域中;
此算法每次只處理正在使用中的對象,因此復制成本比較小,同時復制過去以后還能進行相應的內(nèi)存整理,不會出現(xiàn) “碎片” 問題。當然,此算法的缺點也是很明顯的,就是需要兩倍內(nèi)存空間;
標記-整理 :此算法結合了 “標記-清除” 和 “復制” 兩個算法的優(yōu)點。也是分兩階段,第一階段從根節(jié)點開始標記所有被引用對象,第二階段遍歷整個堆,把清除未標記對象并且把存活對象 “壓縮” 到堆的其中一塊,按順序排放。
此算法避免了 “標記-清除” 的碎片問題,同時也避免了 “復制” 算法的空間問題。
04. root 搜索算法中,哪些可以作為 root?
答:
-
被啟動類(bootstrap 加載器)加載的類和創(chuàng)建的對象;
-
JavaStack 中的引用的對象 (棧內(nèi)存中引用的對象);
-
方法區(qū)中靜態(tài)引用指向的對象;
-
方法區(qū)中常量引用指向的對象;
-
Native 方法中 JNI 引用的對象。
05. GC 什么時候開始?
答:
GC 經(jīng)常發(fā)生的區(qū)域是堆區(qū),堆區(qū)還可以細分為新生代、老年代,新生代還分為一個 Eden 區(qū)和兩個 Survivor 區(qū)。
對象優(yōu)先在 Eden 中分配,當 Eden 中沒有足夠空間時,虛擬機將發(fā)生一次 Minor GC,因為 Java 大多數(shù)對象都是朝生夕滅,所以 Minor GC 非常頻繁,而且速度也很快;
Full GC,發(fā)生在老年代的 GC,當老年代沒有足夠的空間時即發(fā)生 Full GC,發(fā)生 Full GC 一般都會有一次 Minor GC。
大對象直接進入老年代,如很長的字符串數(shù)組,虛擬機提供一個;XX:PretenureSizeThreadhold 參數(shù),令大于這個參數(shù)值的對象直接在老年代中分配,避免在 Eden 區(qū)和兩個 Survivor 區(qū)發(fā)生大量的內(nèi)存拷貝;
發(fā)生 Minor GC 時,虛擬機會檢測之前每次晉升到老年代的平均大小是否大于老年代的剩余空間大小,如果大于,則進行一次 Full GC,如果小于,則查看 HandlePromotionFailure 設置是否允許擔保失敗,如果允許,那只會進行一次 Minor GC,如果不允許,則改為進行一次 Full GC。
06. 內(nèi)存泄漏和內(nèi)存溢出
答:
概念:
內(nèi)存溢出指的是內(nèi)存不夠用了;
內(nèi)存泄漏是指對象可達,但是沒用了。即本該被 GC 回收的對象并沒有被回收;
內(nèi)存泄露是導致內(nèi)存溢出的原因之一;內(nèi)存泄露積累起來將導致內(nèi)存溢出。
內(nèi)存泄漏的原因分析:
長生命周期的對象引用短生命周期的對象;
沒有將無用對象置為 null。
Java 8 相關知識
0.1?HashMap 的底層實現(xiàn)有變化:HashMap 是數(shù)組 + 鏈表 + 紅黑樹(JDK1.8 增加了紅黑樹部分)實現(xiàn)。
02.?JVM 內(nèi)存管理方面,由元空間代替了永久代。
區(qū)別:
1. 元空間并不在虛擬機中,而是使用本地內(nèi)存;
2. 默認情況下,元空間的大小僅受本地內(nèi)存限制;
3. 也可以通過 -XX:MetaspaceSize 指定元空間大小。
03.?Lambda 表達式(也稱為閉包),允許我們將函數(shù)當成參數(shù)傳遞給某個方法,或者把代碼本身當做數(shù)據(jù)處理。
04.?函數(shù)式接口:指的是只有一個函數(shù)的接口,java.lang.Runnable 和 java.util.concurrent.Callable 就是函數(shù)式接口的例子;java8 提供了一個特殊的注解 @Functionallnterface 來標明該接口是一個函數(shù)式接口。
05.?引入重復注解:Java 8 中使用 @Repeatable 注解定義重復注解。
06.?接口中可以實現(xiàn)方法 default 方法。
07.?注解的使用場景拓寬: 注解幾乎可以使用在任何元素上:局部變量、接口類型、超類和接口實現(xiàn)類,甚至可以用在函數(shù)的異常定義上。
08.?新的包 java.time 包
包含了所有關于日期、時間、時區(qū)、持續(xù)時間和時鐘操作的類。
這些類都是不可變的、線程安全的。
網(wǎng)絡協(xié)議相關
01. 三次握手、四次揮手示意圖:
總共有四種狀態(tài):主動建立連接、主動斷開連接、被動建立連和被動斷開連接
兩兩組合還是 4 種組合:
主動建立連接、主動斷開連接會經(jīng)歷的狀態(tài):
SYNC_SENT——ESTABLISHED—-FIN_WAIT_1—-FIN_WAIT_2—-TIME_WAIT
主動建立連接、被動斷開連接會經(jīng)歷的狀態(tài):
SYNC_SENT——ESTABLISHED—-CLOSE_WAIT—-LAST_ACK
被動建立連接、主動斷開連接會經(jīng)歷的狀態(tài):
LISTEN—-SYN_RCVD—-ESTABLISHED—-FIN_WAIT_1—-FIN_WAIT_2—-TIME_WAIT
被動建立連接、被動斷開連接會經(jīng)歷的狀態(tài):
LISTEN—-SYN_RCVD—-ESTABLISHED—-CLOSE_WAIT—-LAST_ACK
02. 滑動窗口機制
由發(fā)送方和接收方在三次握手階段,互相將自己的最大可接收的數(shù)據(jù)量告訴對方。
也就是自己的數(shù)據(jù)接收緩沖池的大小。這樣對方可以根據(jù)已發(fā)送的數(shù)據(jù)量來計算是否可以接著發(fā)送。
在處理過程中,當接收緩沖池的大小發(fā)生變化時,要給對方發(fā)送更新窗口大小的通知。
03. 擁塞避免機制
擁塞:對資源的需求超過了可用的資源。若網(wǎng)絡中許多資源同時供應不足,網(wǎng)絡的性能就要明顯變壞,整個網(wǎng)絡的吞吐量隨之負荷的增大而下降。
擁塞控制:防止過多的數(shù)據(jù)注入到網(wǎng)絡中,使得網(wǎng)絡中的路由器或鏈路不致過載。
擁塞控制方法:
-
慢開始 + 擁塞避免;
-
快重傳 + 快恢復。
04. 瀏覽器中輸入:“www.xxx.com” 之后都發(fā)生了什么?請詳細闡述。
解析:經(jīng)典的網(wǎng)絡協(xié)議問題。
答:
由域名→IP 地址
尋找 IP 地址的過程依次經(jīng)過了瀏覽器緩存、系統(tǒng)緩存、hosts 文件、路由器緩存、 遞歸搜索根域名服務器。
建立 TCP/IP 連接(三次握手具體過程)
由瀏覽器發(fā)送一個 HTTP 請求
經(jīng)過路由器的轉(zhuǎn)發(fā),通過服務器的防火墻,該 HTTP 請求到達了服務器
服務器處理該 HTTP 請求,返回一個 HTML 文件
瀏覽器解析該 HTML 文件,并且顯示在瀏覽器端
這里需要注意:
-
HTTP 協(xié)議是一種基于 TCP/IP 的應用層協(xié)議,進行 HTTP 數(shù)據(jù)請求必須先建立 TCP/IP 連接
-
可以這樣理解:HTTP 是轎車,提供了封裝或者顯示數(shù)據(jù)的具體形式;Socket 是發(fā)動機,提供了網(wǎng)絡通信的能力。
-
兩個計算機之間的交流無非是兩個端口之間的數(shù)據(jù)通信 , 具體的數(shù)據(jù)會以什么樣的形式展現(xiàn)是以不同的應用層協(xié)議來定義的。
05. 常見 HTTP 狀態(tài)碼
1xx(臨時響應)
2xx(成功)
3xx(重定向):表示要完成請求需要進一步操作
4xx(錯誤):表示請求可能出錯,妨礙了服務器的處理
5xx(服務器錯誤):表示服務器在嘗試處理請求時發(fā)生內(nèi)部錯誤
常見狀態(tài)碼:
-
200(成功)
-
304(未修改):自從上次請求后,請求的網(wǎng)頁未修改過。服務器返回此響應時,不會返回網(wǎng)頁內(nèi)容
-
401(未授權):請求要求身份驗證
-
403(禁止):服務器拒絕請求
-
404(未找到):服務器找不到請求的網(wǎng)頁
06. TCP 和 UDP 的區(qū)別:
答:
回答發(fā)送數(shù)據(jù)前是否存在建立連接的過程;
TCP過確認機制,丟包可以重發(fā),保證數(shù)據(jù)的正確性;UDP不保證正確性,只是單純的負責發(fā)送數(shù)據(jù)包;
UDP 是面向報文的。發(fā)送方的 UDP 對應用程序交下來的報文,在添加首部后就向下交付給 IP 層。既不拆分,也不合并,而是保留這些報文的邊界,因 此,應用程序需要選擇合適的報文大小;
UDP 的頭部,只有 8 個字節(jié),相對于 TCP 頭部的 20 個字節(jié)信息包的額外開銷很小。
數(shù)據(jù)庫知識點
01.?MySQL 和 MongoDB 的區(qū)別有哪些?如何選擇?
02.?MongoDB 的優(yōu)缺點有哪些?
(ps 本人對這一塊不是很熟悉,就不附上參考答案了,請各位小伙伴自行學習哈~)
03. 聽說過事務嗎?(必考)
答:
作為單個邏輯工作單元執(zhí)行的一系列操作,滿足四大特性:
原子性(Atomicity):事務作為一個整體被執(zhí)行 ,要么全部執(zhí)行,要么全部不執(zhí)行;
一致性(Consistency):保證數(shù)據(jù)庫狀態(tài)從一個一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€一致狀態(tài);
隔離性(Isolation):多個事務并發(fā)執(zhí)行時,一個事務的執(zhí)行不應影響其他事務的執(zhí)行;
持久性(Durability):一個事務一旦提交,對數(shù)據(jù)庫的修改應該永久保存。
04.?事務的并發(fā)問題有哪幾種?
答:丟失更新、臟讀、不可重復讀以及幻讀。
05. 數(shù)據(jù)庫中的鎖有哪幾種?
答:獨占鎖、排他鎖以及更新鎖。
06. 事務的隔離級別有哪幾種?
答:讀未提交、讀已提交、可重復讀和序列化。
擴展問題:MySQL 事務默認隔離級別是哪個?
答:可重復讀。
07. 數(shù)據(jù)庫的索引有什么作用?(必考)?底層數(shù)據(jù)結構是什么,為什么使用這種數(shù)據(jù)結構?
答:
索引 ?是對數(shù)據(jù)庫表中一列或多列的值進行排序的一種結構,使用索引可快速訪問數(shù)據(jù)庫表中的特定信息;
底層數(shù)據(jù)結構是 B+ 樹;
使用 B+ 樹的原因:查找速度快、效率高,在查找的過程中,每次都能拋棄掉一部分節(jié)點,減少遍歷個數(shù)。( 此時,你應該在白紙上畫出什么是 B+ 樹 )
擴展問題:聚簇索引和非聚簇索引的區(qū)別?
08. MyISAM 和 InnoDB 的區(qū)別有哪些?
答:
-
MyISAM 不支持事務,InnoDB 是事務類型的存儲引擎;
-
MyISAM 只支持表級鎖,BDB 支持頁級鎖和表級鎖,默認為頁級鎖;而 InnoDB 支持行級鎖和表級鎖,默認為行級鎖;
-
MyISAM 引擎不支持外鍵,InnoDB 支持外鍵;
-
MyISAM 引擎的表在大量高并發(fā)的讀寫下會經(jīng)常出現(xiàn)表損壞的情況;
-
對于 count( ) 查詢來說 MyISAM 更有優(yōu)勢;
-
InnoDB 是為處理巨大數(shù)據(jù)量時的最大性能設計,它的 CPU 效率可能是任何其它基于磁盤的關系數(shù)據(jù)庫引擎所不能匹敵的;
-
MyISAM 支持全文索引(FULLTEXT),InnoDB 不支持;
-
MyISAM 引擎的表的查詢、更新、插入的效率要比 InnoDB 高。
最主要的區(qū)別是:MyISAM 表不支持事務、不支持行級鎖、不支持外鍵。 InnoDB 表支持事務、支持行級鎖、支持外鍵。(可直接回答這個)
09. 數(shù)據(jù)庫中 Where、group by、having 關鍵字:
答:??
關鍵字作用:
where 子句用來篩選 from 子句中指定的操作所產(chǎn)生的的行;
group by 子句用來分組 where 子句的輸出;
having 子句用來從分組的結果中篩選行;
having 和 where 的區(qū)別:
語法類似,where 搜索條件在進行分組操作之前應用;having 搜索條件在進行分組操作之后應用;
having 可以包含聚合函數(shù) sum、avg、max 等;
having 子句限制的是組,而不是行。
當同時含有 where 子句、group by 子句 、having 子句及聚集函數(shù)時,執(zhí)行順序如下:
執(zhí)行 where 子句查找符合條件的數(shù)據(jù);
使用 group by 子句對數(shù)據(jù)進行分組;對 group by 子句形成的組運行聚集函數(shù)計算每一組的值;最后用 having 子句去掉不符合條件的組。
10.?還有一些問題,如 MySQL 和 SQL Server 用法上的區(qū)別、limit 關鍵字的使用等問題。
框架相關知識
JavaWeb 開發(fā)經(jīng)典的 3 層框架:Web 層、Service 層(業(yè)務邏輯層)和 Dao 層(數(shù)據(jù)訪問層)
-
Web 層:包含 JSP 和 Servlet 等與 Web 相關的內(nèi)容;
-
業(yè)務層:只關心業(yè)務邏輯;
-
數(shù)據(jù)層:封裝了對數(shù)據(jù)庫的訪問細節(jié)。
Spring 知識點
01. Spring 的 IOC 和 AOP 有了解嗎?
答:
-
IOC:控制反轉(zhuǎn),(解耦合)將對象間的依賴關系交給 Spring 容器,使用配置文件來創(chuàng)建所依賴的對象,由主動創(chuàng)建對象改為了被動方式;
-
AOP:面向切面編程,將功能代碼從業(yè)務邏輯代碼中分離出來。
02. AOP 的實現(xiàn)方式有哪幾種?如何選擇?(必考)
答:
JDK 動態(tài)代理實現(xiàn)和 cglib 實現(xiàn)。
選擇:
如果目標對象實現(xiàn)了接口,默認情況下會采用 JDK 的動態(tài)代理實現(xiàn) AOP,也可以強制使用 cglib 實現(xiàn) AOP;
如果目標對象沒有實現(xiàn)接口,必須采用 cglib 庫,Spring 會自動在 JDK 動態(tài)代理和 cglib 之間轉(zhuǎn)換。
擴展:JDK 動態(tài)代理如何實現(xiàn)?(加分點)
答:
JDK 動態(tài)代理,只能對實現(xiàn)了接口的類生成代理,而不是針對類,該目標類型實現(xiàn)的接口都將被代理。
原理是通過在運行期間創(chuàng)建一個接口的實現(xiàn)類來完成對目標對象的代理。
定義一個實現(xiàn)接口 InvocationHandler 的類;
通過構造函數(shù),注入被代理類;
實現(xiàn) invoke( Object proxy, Method method, Object[] args)方法;
在主函數(shù)中獲得被代理類的類加載器;
使用 Proxy.newProxyInstance( ) 產(chǎn)生一個代理對象;
通過代理對象調(diào)用各種方法。
03. Spring MVC 的核心控制器是什么?消息處理流程有哪些?
答:
核心控制器為 DispatcherServlet。消息流程如下:
04. 其他問題包括:重定向和轉(zhuǎn)發(fā)的區(qū)別、動態(tài)代理和靜態(tài)代理的區(qū)別等。
Mybatis 知識點
關于 MyBatis 主要考察占位符#和 $ 的區(qū)別,區(qū)別如下:
符號將傳入的數(shù)據(jù)都當做一個字符串,會對自動傳入的數(shù)據(jù)加一個雙引號;
$ 符號將傳入的數(shù)據(jù)直接顯示生成 SQL 中;
符號存在預編譯的過程,,對問號賦值,防止 SQL 注入;
$ 符號是直譯的方式,一般用在 order by ${列名}語句中;
能用#號就不要用 $ 符號。
大數(shù)據(jù)相關知識
01. KafKa 基本特性:
答:
快速持久化、支持批量讀寫消息、支持消息分區(qū),提高了并發(fā)能力、支持在線增加分區(qū)、支持為每個分區(qū)創(chuàng)建多個副本。
擴展:為什么可以實現(xiàn)快速持久化?
答:
KafKa 將消息保存在磁盤中,并且讀寫磁盤的方式是順序讀寫,避免了隨機讀寫磁盤(尋道時間過長)導致的性能瓶頸;磁盤的順序讀寫速度超過內(nèi)存隨機讀寫。
02. 核心概念
答:
-
生產(chǎn)者(Producer):?生產(chǎn)消息,并且按照一定的規(guī)則推送到 Topic 的分區(qū)中。
-
消費者(Consumer):?從 Topic 中拉去消息,并且進行消費。
-
主題(Topic):?用于存儲消息的邏輯概念,是一個消息集合。
-
分區(qū)(partition):
-
每個 Topic 可以劃分為多個分區(qū),每個消息在分區(qū)中都會有一個唯一編號 offset
-
kafka 通過 offset 保證消息在分區(qū)中的順序
-
同一 Topic 的不同分區(qū)可以分配在不同的 Broker 上
-
partition 以文件的形式存儲在文件系統(tǒng)中。
副本(replica):
KafKa 對消息進行了冗余備份,每個分區(qū)有多個副本,每個副本中包含的消息是 “一樣” 的。
每個副本中都會選舉出一個 Leader 副本,其余為 Follower 副本,Follower 副本僅僅將數(shù)據(jù)從 Leader 副本拉去到本地,然后同步到自己的 Log 中。
消費者組(Consumer Group):?每個 consumer 都屬于一個 consumer group,每條消息只能被 consumer group 中的一個 Consumer 消費,但可以被多個 consumer group 消費。
Broker:
一個單獨的 server 就是一個 Broker;
主要工作:接收生產(chǎn)者發(fā)過來的消息,分配 offset,并且保存到磁盤中;
Cluster&Controller:
多個 Broker 可以組成一個 Cluster,每個集群選舉一個 Broker 來作為 Controller,充當指揮中心
Controller 負責管理分區(qū)的狀態(tài),管理每個分區(qū)的副本狀態(tài),監(jiān)聽 ZooKeeper 中數(shù)據(jù)的變化等工作
保留策略和日志壓縮:
不管消費者是否已經(jīng)消費了消息,KafKa 都會一直保存這些消息(持久化到磁盤);
通過保留策略,定時刪除陳舊的消息;
日志壓縮,只保留最新的 Key-Value 對。
關于副本機制:(加分點)
ISR 集合 :表示當前 “可用” 且消息量與 Leader 相差不多的副本集合。滿足條件如下:
副本所在節(jié)點必須維持著與 ZooKeeper 的連接;
副本最后一條信息的 offset 與 Leader 副本的最后一條消息的 offset 之間的差值不能超過指定的閾值。
HW&LEO:
HW 標記了一個特殊的 offset,當消費者處理消息的時候,只能拉取到 HW 之前的消息;
HW 也是由 Leader 副本管理的;
LEO(Log End Offset)是所有副本都會有的一個 offset 標記。
ISR、HW 和 LEO 的工作配合:
producer 向此分區(qū)中推送消息;
Leader 副本將消息追加到 Log 中,并且遞增其 LEO;
Follower 副本從 Leader 副本中拉取消息進行同步;
Follower 副本將消息更新到本地 Log 中,并且遞增其 LEO;
當 ISR 集合中的所有副本都完成了對 offset 的消息同步,Leader 副本會遞增其 HW
KafKa 的容災機制:通過分區(qū)的副本 Leader 副本和 Follower 副本來提高容災能力。
Linux 常見命令
01. grep、sed 以及 awk 命令
解析:awk 命令如果可以掌握,是面試中的一個 ?加分點。
02. 文件和目錄:
ls 顯示當前目錄下的文件和目錄:
ls -F 可以區(qū)分文件和目錄;
ls -a 可以把隱藏文件和普通文件一起顯示出來;
ls -R 可以遞歸顯示子目錄中的文件和目錄;
ls -l 顯示長列表;
ls -l test 過濾器,查看某個特定文件信息。可以只查看 test 文件的信息。
03. 處理文件方面的命令有:touch、cp、 In、mv、rm、 ? ? ? ? ?
04. 處理目錄方面的命令:mkdir
05. 查看文件內(nèi)容:file、cat、more、less、tail、head
06. 監(jiān)測程序命令:ps、top
eg. 找出進程名中包括 java 的所有進程:ps -ef | grep java
top 命令 實時監(jiān)測進程
top 命令輸出的第一部分:顯示系統(tǒng)的概括。
第一行顯示了當前時間、系統(tǒng)的運行時間、登錄的用戶數(shù)和系統(tǒng)的平均負載(平均負載有 3 個值:最近 1min 5min 15min);
第二行顯示了進程的概要信息,有多少進程處于運行、休眠、停止或者僵化狀態(tài);
第三行是 CPU 的概要信息;
第四行是系統(tǒng)內(nèi)存的狀態(tài)。
07. ps 和 top 命令的區(qū)別:
ps 看到的是命令執(zhí)行瞬間的進程信息 , 而 top 可以持續(xù)的監(jiān)視;
ps 只是查看進程 , 而 top 還可以監(jiān)視系統(tǒng)性能 , 如平均負載 ,cpu 和內(nèi)存的消耗;
另外 top 還可以操作進程 , 如改變優(yōu)先級 (命令 r) 和關閉進程 (命令 k);
ps 主要是查看進程的,關注點在于查看需要查看的進程;
top 主要看 cpu, 內(nèi)存使用情況,及占用資源最多的進程由高到低排序,關注點在于資源占用情況。
08. 壓縮數(shù)據(jù)
tar -xvf 文件名;
tar -zxvf 文件名;
tar -cvzf 文件名。
09. 結束進程:kill PID 或者 kill all
轉(zhuǎn)載于:https://my.oschina.net/u/3459265/blog/1801894
總結
- 上一篇: vue基础-简介
- 下一篇: 统计分析与R软件-chapter2-5