1. JDK和JRE的區別
jdk是java開發工具包。提供了Java運行環境
jre爲java提供了java所需的運行環境
2. ==和equals的區別是什麼?*
==:
和基本類型相比:比較值是否相等
和引用類型相比:比較引用是否相等
equals:
equals比較的是值是否相等
3. 兩個對象的hashcode()相同,則equals也一定爲true,對嗎?*
不對,兩個對象的hashcode()相同,equals也不一定爲true
如果兩個對象equals爲true,那麼他們的hashcode一定相等
4. final在java有什麼作用*
final修飾的類爲最終類,該類不能被繼承
final修飾的方法不能被重寫
final修飾的變量爲常量,常量必須初始化,且不能被更改
5. Math.round(-1.5)等於多少
等於-1。向上取整
6. String是基礎數據類型嗎*
不是。String是引用數據類型
基礎數據類型有:byte,short,int,char,boolean,float,long,double
7. java操作字符串的類有哪些,它們有什麼區別?*
操作字符串的類有:String,StringBuffer,StringBuilder
String:聲明的是不可變的對象。創建後就不能被修改
StringBuffer和StringBuilder區別在於,StringBuffer是線程安全的,StringBuilder是線程非安全的
單線程推薦使用StringBuilder,多線程推薦使用StringBuffer
8. String str="i"和String str=new String(“i”)是否一樣
不一樣。因爲分配的內存不一樣
String str="i"會分配到常量池中。new String(“i”)會被分配到堆內存中
9. 如何實現字符串反轉*
可以使用StringBuffer和StringBuilder的reverse()方法
10. String類的常用方法都有哪些方法*
indexOf():返回指定字的索引
charAt():返回指定索引的字符
replace():字符串替換
trim():取出字符串兩端的空格
split():分割字符串,返回分割後的字符串數組
getBytes():返回字符串的byte類型數組
length():返回字符串的長度
toLowerCase():將字符串轉成小寫字母
toUpperCase():將字符串轉換爲大寫字母
subString():截取字符串
equals():字符串比較
11. 抽象類一定要有抽象方法嗎
不需要。抽象類不一定要有抽象方法
12. 普通類和抽象類有哪些區別
普通類不能包含抽象方法,抽象類可以包含抽象方法
抽象類不能被實例化,普通類可以直接被實例化
13. 接口和抽象類有什麼區別*
- 抽象類的子類使用extends來繼承;接口必須使用implements實現接口
- 抽象類可以有構造函數,接口不能有。
- 抽象可以有main方法且可以運行;接口不能有
- 接口的方法默認使用public修飾;抽象類可以被任意修飾符修飾
14. 抽象類能被final修飾嗎*
不能。抽象類就是用來被繼承的,如果被final修飾,就不能被繼承。
15. java的IO分爲哪幾種*
按功能來分:輸入流,輸出流
按類型來分:字節流和字符流
字節流按8位傳輸以字節單位輸入輸出數據
字符流按16位傳輸以字節單位輸入輸出數據
16. BIO、NIO、AIO有什麼區別
BIO:Block IO同步阻塞IO,就是我們平常使用的IO,特點是簡單方便,併發處理能力低
NIO:New IO同步非阻塞IO,是傳統IO的升級,客戶端通過Channel通訊,實現了多路複用
AIO:是NIO的升級,實現了異步非阻塞IO,異步IO的操作基於事件和回調機制
17. Files的常用方法都有哪些
Files.exists():檢測文件路徑是否存在
Files.createFile():創建文件
Files.createDirectory():創建文件夾
Files.delete():刪除一個文件或目錄
Files.copy():複製文件
Files.move():移動文件
Files.size():讀取文件
Files.Write():寫入文件
集合
18. Java常用的容器有哪些
Conllection:
1. List 1. Vector 1. Stack 2. ArrayList 3. LinkedList
- Queue
- Set
- HashSet
- LinkHashSet
- TreeSet
Map:
HashMap
- TreeMap
19. Colleoction和Collections有什麼區別*
Collection是一個集合接口。提供了集合對象進行基本操作的通用接口方法
Collections是集合類的一個工具類,提供了一系列的靜態方法,用於集合的排序,查找等各種操作
20. List、Set、Map之間的區別是什麼
比較 List Set Map 繼承接口 Colleoction Colleoction 常見實現類 AbstracList(常見子類:ArrayList、LinkedList、Vector) AbstracSet(常見子類:HashSet、LinkedHashSet、TreeSet) HashMap、HashTable 常見方法 add()、remove()、clear()、get()、contains()、size() add()、remove()、clear()、contains()、size() put()、get()、remove()、clear()、containsKey()、KeySet()、values()、Size() 元素 可重複 不可重複 不可重複 順序 有序 無序 線程安全 Vector線程安全 Hashtable線程安全
21. hashMap和HashTable的區別*
hashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKey()方法
hashTable同步的而hashMap是非同步的,效率比hashTable高
22.如何決定使用hashmap還是Treemap
對於map中插入,刪除,定位元素這類操作,hashmap是最好的選擇。
如果對有序的key進行遍歷,Treemap是更好的選擇
23. 說一說hashmap的原理*
Hashmap是基於哈希表的map接口的非同步實現。此實現提供所有可選的映射操作,並允許使用null值和null鍵。此類不保證該順序恆久不變
hashmap實際上是一個鏈表散列的數據結構,即數組和鏈表的結合體
當我們往hashmap中put元素時,首先根據key的hashcode重新計算hash值,根據hash值的到這個元素在數組中的位置,如果該數組在該位置上存放了其他元素,那麼在這個位置上的元素將以鏈表的形式進行存放,新加入的放在鏈頭,最先加入的放在鏈尾,如果數組中該位置沒有元素,就直接將該元素存放在數組的該位置上
jdk1.8對hashmap進行了優化,當鏈表中的節點數據超過8個之後,該鏈表會轉爲紅黑樹來提高查詢效率。
24. 說一下hashSet的實現原理*
hashSet底層有hashmap實現
hashset的值存放於hashMap的key上
hashset的value統一位PRESENT
25. ArrayList和LinkedList的區別是什麼?*
最明顯的區別是ArrayList底層的數據結構是數組,支持隨機訪問。
LinkedList底層數據結構是雙向循環鏈表,不支持隨機訪問。
26. 如何實現數組和List之間的轉換*
List轉換爲數組:調用ArrayList的toArray方法
數組轉換爲List:調用Arrays的asList方法
27. ArrayList和Vector的區別是什麼*
Vector是同步的,ArrayList則不是
ArrayList比Vector快,它因爲有同步,不會過載
ArrayList更加通用,因爲可以使用conllections工具類輕易的過去同步列表和只讀列表
28. Array和ArrayList的區別*
Array可以容納基本類型和對象,ArrayList只能容納對象
Array是指定大小的,ArrayList的大小是固定的
Array沒有ArrayList那麼多功能。
29. 在Queue中poll()和remove()有什麼區別
poll()和remove()都是從隊列取出一個元素,但是poll()在獲取元素失敗會返回空,remove()失敗會拋出異常
30. 哪些集合類是線程安全的
vector,statck,hashtable,enumeration
31. 迭代器Iterator是什麼
迭代器是一種設計模式,它是一個對象,可以進行遍歷並選擇序列中的對象,而開發人員不需要了解該序列的底層結構。迭代器通常被稱爲輕量級對象,因爲創建它的代價小
32. Iterator怎麼使用?有什麼特點
- 使用方法iterator()要求容器返回一個iterator;第一次調用iterator的next()方法時,返回的序列是第一個元素。
- 使用next()方法獲得序列的下一個元素
- 使用hasnext()方法檢查序列中是否還有元素
- 使用remove()方法將迭代器新返回的元素刪除
iterator是java迭代器最簡單的實現,爲List設計的ListIterator具有更多的功能,它可以從兩個方向進行遍歷List,也可以從List中插入和刪除元素。
33. Iterator和ListIterator有什麼區別
- Iterator可以遍歷Set和List集合,ListIterator只能遍歷List
- Iterator對集合只能是前向遍歷,ListIterator可以前向和後向遍歷
- ListIterator實現了Iterator接口,幷包含其他功能,比如添加元素,替換元素等等
多線程
34.並行和併發有什麼區別
- 並行是指兩個或者多個事件在同一時刻發生;併發實質兩個或多個事件在統一時間間隔發生
- 並行是在不同實體上的多個事件,併發是同一實體的多個事件
- 在一臺處理器上同時處理多個任務,在多臺處理器上同時處理多個任務
所以併發編程的目標是充分的利用處理器的每一個核,以達到最高的處理性能
35.線程和進程的區別
進程是程序運行和資源分配的基本單位,一個程序至少有一個進程,一個進程至少有一個線程
線程是進程的一個實體,是cpu調度和分派的基本單位,是比程序更小的能獨立運行的基本單位。
36. 守護線程是什麼
守護線程是一個服務線程,準確的說就是服務其他的線程
37. 創建線程有哪幾種方式
- 繼承Thread類創建線程
- 定義Thread類的子類,重寫該類的run方法,該run方法的方法體就代表了線程要完成的任務
- 創建Thread子類的實例,即創建了線程對象
- 調用線程對象的start()方法來啓動線程
- 通過runnable接口創建線程
- 定義runnable接口實現類,並重寫該類的run方法,該run方法的方法體同樣是該線程的線程執行體
- 創建runnable實現類的實例,並依次實例做爲Thread的target來創建Thread對象,該Thread對象纔是真正的線程對象
- 調用線程對象的start方法啓動該線程
- 通過Callable和Future方法創建線程
38. 線程有哪些狀態?
線程通常有5種狀態;
- 創建狀態,2. 就緒狀態,3. 運行狀態,4. 阻塞狀態,5. 死亡狀態
39. sleep()和wait()的區別?
sleep():方法是線程類的靜態方法,調用線程進入睡眠狀態,讓出執行機會給其他線程,等到休眠結束後,線程進入就緒狀態和其他線程一起競爭cpu的執行事件
wait():是Object類的方法,當一個線程執行到wait方法時,它就進入到一個和該對象相關的等待池,同時釋放對象的機鎖,使得其他線程能夠訪問,可以通過notify,notifyAll方法來喚醒等待的線程
40. notify()和 notifyAll()有什麼區別?
如果線程調用了對象的 wait()方法,那麼線程便會處於該對象的等待池中,等待池中的線程不會去競爭該對象的鎖。
當有線程調用了對象的 notifyAll()方法或 notify()方法,被喚醒的的線程便會進入該對象的鎖池中,鎖池中的線程會去競爭該對象鎖。也就是說,調用了notify後只要一個線程會由等待池進入鎖池,而notifyAll會將該對象等待池內的所有線程移動到鎖池中,等待鎖競爭。
優先級高的線程競爭到對象鎖的概率大,假若某線程沒有競爭到該對象鎖,它還會留在鎖池中,唯有線程再次調用 wait()方法,它纔會重新回到等待池中。而競爭到對象鎖的線程則繼續往下執行,直到執行完了 synchronized 代碼塊,它會釋放掉該對象鎖,這時鎖池中的線程會繼續競爭該對象鎖。
41. 線程的 run()和 start()有什麼區別?
每個線程都是通過某個特定Thread對象所對應的方法run()來完成其操作的,方法run()稱爲線程體。通過調用Thread類的start()方法來啓動一個線程。
start()方法來啓動一個線程,真正實現了多線程運行。這時無需等待run方法體代碼執行完畢,可以直接繼續執行下面的代碼; 這時此線程是處於就緒狀態, 並沒有運行。 然後通過此Thread類調用方法run()來完成其運行狀態, 這裏方法run()稱爲線程體,它包含了要執行的這個線程的內容, Run方法運行結束, 此線程終止。然後CPU再調度其它線程。
run()方法是在本線程裏的,只是線程裏的一個函數,而不是多線程的。 如果直接調用run(),其實就相當於是調用了一個普通函數而已,直接待用run()方法必須等待run()方法執行完畢才能執行下面的代碼,所以執行路徑還是隻有一條,根本就沒有線程的特徵,所以在多線程執行時要使用start()方法而不是run()方法。
42. 創建線程池有哪幾種方式?
newFixedThreadPool(int nThreads)
newCachedThreadPool()
newSingleThreadExecutor()
newScheduledThreadPool(int corePoolSize)
43. 線程池都有哪些狀態?
線程池有5種狀態:Running、ShutDown、Stop、Tidying、Terminated。
44. 線程池中 submit()和 execute()方法有什麼區別?
- 接收的參數不一樣
- submit有返回值,而execute沒有
- submit方便Exception處理
45.在 java 程序中怎麼保證多線程的運行安全?
原子性:提供互斥訪問,同一時刻只能有一個線程對數據進行操作
可見性:一個線程對主內存的修改可以及時地被其他線程看到
有序性:一個線程觀察其他線程中的指令執行順序,由於指令重排序,該觀察結果一般雜亂無序
46. 多線程鎖的升級原理是什麼?
在Java中,鎖共有4種狀態,級別從低到高依次爲:無狀態鎖,偏向鎖,輕量級鎖和重量級鎖狀態,這幾個狀態會隨着競爭情況逐漸升級。鎖可以升級但不能降級。
47. 什麼是死鎖?
死鎖是指兩個或兩個以上的進程在執行過程中,由於競爭資源或者由於彼此通信而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱爲死鎖進程.
48. 怎麼防止死鎖?
死鎖的四個必要條件:
互斥條件:進程對所分配到的資源不允許其他進程進行訪問,若其他進程訪問該資源,只能等待,直至佔有該資源的進程使用完成後釋放該資源
- 請求和保持條件:進程獲得一定的資源之後,又對其他資源發出請求,但是該資源可能被其他進程佔有,此事請求阻塞,但又對自己獲得的資源保持不放
- 不可剝奪條件:是指進程已獲得的資源,在未完成使用之前,不可被剝奪,只能在使用完後自己釋放
- 環路等待條件:是指進程發生死鎖後,若干進程之間形成一種頭尾相接的循環等待資源關係
這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之 一不滿足,就不會發生死鎖。
在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確 定資源的合理分配算法,避免進程永久佔據系統資源。
49.說一下 synchronized 底層實現原理?
synchronized可以保證方法或者代碼塊在運行時,同一時刻只有一個方法可以進入到臨界區,同時它還可以保證共享變量的內存可見性。
Java中每一個對象都可以作爲鎖,這是synchronized實現同步的基礎:
普通同步方法,鎖是當前實例對象
- 普通同步方法,鎖是當前實例對象
- 靜態同步方法,鎖是當前類的class對象
50. synchronized 和 volatile 的區別是什麼?
volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取; synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的
volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性。
volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化。
51. synchronized 和 Lock 有什麼區別?
首先synchronized是java內置關鍵字,在jvm層面,Lock是個java類;
synchronized無法判斷是否獲取鎖的狀態,Lock可以判斷是否獲取到鎖;
synchronized會自動釋放鎖,Lock需在finally中手工釋放鎖,否則容易造成線程死鎖;
用synchronized關鍵字的兩個線程1和線程2,如果當前線程1獲得鎖,線程2線程等待。如果線程1阻塞,線程2則會一直等待下去,而Lock鎖就不一定會等待下去,如果嘗試獲取不到鎖,線程可以不用一直等待就結束了;
synchronized的鎖可重入、不可中斷、非公平,而Lock鎖可重入、可判斷、可公平;
Lock鎖適合大量同步的代碼的同步問題,synchronized鎖適合代碼少量的同步問題。
52. synchronized 和 ReentrantLock 區別是什麼?
synchronized是和if、else、for、while一樣的關鍵字,ReentrantLock是類,這是二者的本質區別。既然ReentrantLock是類,那麼它就提供了比synchronized更多更靈活的特性,可以被繼承、可以有方法、可以有各種各樣的類變量,ReentrantLock比synchronized的擴展性體現在幾點上:
ReentrantLock可以對獲取鎖的等待時間進行設置,這樣就避免了死鎖
- ReentrantLock可以對獲取鎖的等待時間進行設置,這樣就避免了死鎖
- ReentrantLock可以獲取各種鎖的信息
另外,二者的鎖機制其實也是不一樣的:ReentrantLock底層調用的是Unsafe的park方法加鎖,synchronized操作的應該是對象頭中mark word。
反射
53. 什麼是反射?
反射主要是指程序可以訪問、檢測和修改它本身狀態或行爲的一種能力
在Java運行時環境中,對於任意一個類,能否知道這個類有哪些屬性和方法?對於任意一個對象,能否調用它的任意一個方法:
在運行時判斷任意一個對象所屬的類。
- 在運行時構造任意一個類的對象。
- 在運行時判斷任意一個類所具有的成員變量和方法。
- 在運行時判斷任意一個類所具有的成員變量和方法。
54. 什麼是 java 序列化?什麼情況下需要序列化?
簡單說就是爲了保存在內存中的各種對象的狀態,並且可以把保存的對象狀態再讀出來。雖然你可以用你自己的各種各樣的方法來保存object states,但是Java給你提供一種應該比你自己好的保存對象狀態的機制,那就是序列化。
什麼情況下需要序列化:
- 當你想把的內存中的對象狀態保存到一個文件中或者數據庫中時候;
- 當你想用套接字在網絡上傳送對象的時候;
- 當你想通過RMI傳輸對象的時候;
55. 動態代理是什麼?有哪些應用?
當想要給實現了某個接口的類中的方法,加一些額外的處理。比如說加日誌,加事務等。可以給這個類創建一個代理,故名思議就是創建一個新的類,這個類不僅包含原來類方法的功能,而且還在原來的基礎上添加了額外處理的新類。這個代理類並不是定義好的,是動態生成的。具有解耦意義,靈活,擴展性強。
動態代理的應用:
1. Spring的AOP 2. 加事務 3. 加權限 4. 加日誌
56. 怎麼實現動態代理?
首先必須定義一個接口,還要有一個InvocationHandler處理類。再有一個工具類Proxy。利用到InvocationHandler,拼接代理類源碼,將其編譯生成代理類的二進制碼,利用加載器加載,並將其實例化產生代理對象,最後返回。
Java Web
57. jsp 和 servlet 有什麼區別?
jsp經編譯後就變成了Servlet.
jsp更擅長表現於頁面顯示,servlet更擅長於邏輯控制。
Servlet中沒有內置對象,Jsp中的內置對象都是必須通過HttpServletRequest對象,HttpServletResponse對象以及HttpServlet對象得到。
Jsp是Servlet的一種簡化,使用Jsp只需要完成程序員需要輸出到客戶端的內容,Jsp中的Java腳本如何鑲嵌到一個類中,由Jsp容器完成。而Servlet則是個完整的Java類,這個類的Service方法用於生成對客戶端的響應。
58. jsp 有哪些內置對象?作用分別是什麼?
JSP有9個內置對象:
- request:封裝客戶端的請求,其中包含來自GET或POST請求的參數;
- response:封裝服務器對客戶端的響應;
- pageContext:通過該對象可以獲取其他對象;
- session:封裝用戶會話的對象;
- application:封裝服務器運行環境的對象;
- out:輸出服務器響應的輸出流對象;
- config:Web應用的配置對象;
- page:JSP頁面本身
- exception:封裝頁面拋出異常的對象。
59. 說一下 jsp 的 4 種作用域?
JSP中的四種作用域包括page、request、session和application,具體來說:
- page代表與一個頁面相關的對象和屬性。
- request代表與Web客戶機發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個Web組件;需要在頁面顯示的臨時數據可以置於此作用域。
- session代表與某個用戶與服務器建立的一次會話相關的對象和屬性。跟某個用戶相關的數據應該放在用戶自己的session中。
- application代表與整個Web應用程序相關的對象和屬性,它實質上是跨越整個Web應用程序,包括多個頁面、請求和會話的一個全局作用域。
60.說一下 session 的工作原理?
session是一個存在服務器上的類似於一個散列表格的文件。裏面存有我們需要的信息,在我們需要用的時候可以從裏面取出來。類似於一個大號的map吧,裏面的鍵存儲的是用戶的sessionid,用戶向服務器發送請求的時候會帶上這個sessionid。這時就可以從中取出對應的值了。
61. 如果客戶端禁止 cookie 能實現 session 還能用嗎?
Session是用Session ID來確定當前對話所對應的服務器Session,而Session ID是通過Cookie來傳遞的,禁用Cookie相當於失去了Session ID,也就得不到Session了。
62. spring mvc 和 struts 的區別是什麼?
攔截機制的不同:
Struts2是類級別的攔截,每次請求就會創建一個Action,和Spring整合時Struts2的ActionBean注入作用域是原型模式prototype,然後通過setter,getter吧request數據注入到屬性。
SpringMVC是方法級別的攔截,一個方法對應一個Request上下文,所以方法直接基本上是獨立的,獨享request,response數據。
Struts2有自己的攔截Interceptor機制,SpringMVC這是用的是獨立的Aop方式,這樣導致Struts2的配置文件量還是比SpringMVC大。
底層框架的不同
Struts2採用Filter實現
SpringMVC採用Servlet實現。
性能方面
SpringMVC開發效率和性能高於Struts2。
Struts2是類級別的攔截,每次請求對應實例一個新的Action,需要加載所有的屬性值注入
SpringMVC實現了零配置,由於SpringMVC基於方法的攔截,有加載一次單例模式bean注入。
配置方面
spring MVC和Spring是無縫的。從這個項目的管理和安全上也比Struts2高。
63. 如何避免 sql 注入?
- PreparedStatement(簡單又有效的方法)
- 使用正則表達式過濾傳入的參數
- 字符串過濾
- JSP中調用該函數檢查是否包函非法字符
- JSP頁面判斷代碼
64. 什麼是 XSS 攻擊,如何避免?
XSS攻擊又稱CSS,全稱Cross Site Script (跨站腳本攻擊),其原理是攻擊者向有XSS漏洞的網站中輸入惡意的 HTML 代碼,當用戶瀏覽該網站時,這段 HTML 代碼會自動執行,從而達到攻擊的目的。
XSS防範的總體思路是:對輸入(和URL參數)進行過濾,對輸出進行編碼。
65**. 什麼是 CSRF 攻擊,如何避免?**
CSRF也被稱爲 one-click attack或者 session riding,中文全稱是叫跨站請求僞造。
攻擊者通過僞造用戶的瀏覽器的請求,向訪問一個用戶自己曾經認證訪問過的網站發送出去,使目標網站接收並誤以爲是用戶的真實操作而去執行命令。
攻擊者利用網站對請求的驗證漏洞而實現這樣的攻擊行爲,網站能夠確認請求來源於用戶的瀏覽器,卻不能驗證請求是否源於用戶的真實意願下的操作行爲。
如何避免:
1. 驗證 HTTP Referer 字段 2. 使用驗證碼 3. 在請求地址中添加token並驗證 4. 在HTTP 頭中自定義屬性並驗證
異常
66. throw 和 throws 的區別?
throws是用來聲明一個方法可能拋出的所有異常信息,throws是將異常聲明但是不處理,而是將異常往上傳,誰調用我就交給誰處理。
throw則是指拋出的一個具體的異常類型。
67. final、finally、finalize 有什麼區別?
final可以修飾類、變量、方法,修飾類表示該類不能被繼承、修飾方法表示該方法不能被重寫、修飾變量表示該變量是一個常量不能被重新賦值。
finally一般作用在try-catch代碼塊中,在處理異常的時候,通常我們將一定要執行的代碼方法finally代碼塊中,表示不管是否出現異常,該代碼塊都會執行,一般用來存放一些關閉資源的代碼。
finalize是一個方法,屬於Object類的一個方法,而Object類是所有類的父類,該方法一般由垃圾回收器來調用,當我們調用System的gc()方法的時候,由垃圾回收器調用finalize(),回收垃圾。
68.try-catch-finally 中哪個部分可以省略?
catch 可以省略
69.try-catch-finally 中,如果 catch 中 return 了,finally 還會執行嗎?
會執行,在 return 前執行。
70. 常見的異常類有哪些?
- NullPointerException:當應用程序試圖訪問空對象時,則拋出該異常。
- SQLException:提供關於數據庫訪問錯誤或其他錯誤信息的異常。
- IndexOutOfBoundsException:指示某排序索引超出範圍時拋出。
- NumberFormatException:當應用程序試圖將字符串轉換成一種數值類型,但該字符串不能轉換爲適當格式時,拋出該異常。
- FileNotFoundException:當試圖打開指定路徑名錶示的文件失敗時,拋出此異常。
- IOException:當發生某種I/O異常時,拋出此異常。此類是失敗或中斷的I/O操作生成的異常的通用類。
- ClassCastException:當試圖將對象強制轉換爲不是實例的子類時,拋出該異常。
- ArrayStoreException:試圖將錯誤類型的對象存儲到一個對象數組時拋出的異常。
- IllegalArgumentException:拋出的異常表明向方法傳遞了一個不合法或不正確的參數。
- ArithmeticException:當出現異常的運算條件時,拋出此異常。
- NegativeArraySizeException:如果應用程序試圖創建大小爲負的數組,則拋出該異常
- NoSuchMethodException:無法找到某一特定方法時,拋出該異常。
- SecurityException:由安全管理器拋出的異常,指示存在安全侵犯。
- UnsupportedOperationException:當不支持請求的操作時,拋出該異常。
- RuntimeExceptionRuntimeException:是那些可能在Java虛擬機正常運行期間拋出的異常的超類。
網絡
71. http 響應碼 301 和 302 代表的是什麼?有什麼區別?
301,302 都是HTTP狀態的編碼,都代表着某個URL發生了轉移。
區別:
- 301 redirect: 301 代表永久性轉移(
- 302 redirect: 302 代表暫時性轉移
72. forward 和 redirect 的區別?
Forward和Redirect代表了兩種請求轉發方式:直接轉發和間接轉發。
直接轉發方式(Forward),客戶端和瀏覽器只發出一次請求,Servlet、HTML、JSP或其它信息資源,由第二個信息資源響應該請求,在請求對象request中,保存的對象對於每個信息資源是共享的。
**間接轉發方式(Redirect)**實際是兩次HTTP請求,服務器端在響應第一次請求的時候,讓瀏覽器再向另外一個URL發出請求,從而達到轉發的目的。
73. 簡述 tcp 和 udp的區別?
- TCP面向連接;UDP是無連接的,即發送數據之前不需要建立連接。
- TCP提供可靠的服務。也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付。
- Tcp通過校驗和,重傳控制,序號標識,滑動窗口、確認應答實現可靠傳輸。如丟包時的重發控制,還可以對次序亂掉的分包進行順序控制。
- UDP具有較好的實時性,工作效率比TCP高,適用於對高速傳輸和實時性有較高的通信或廣播通信。
- 每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信
- TCP對系統資源要求較多,UDP對系統資源要求較少。
74.tcp 爲什麼要三次握手,兩次不行嗎?爲什麼?
爲了實現可靠數據傳輸, TCP 協議的通信雙方, 都必須維護一個序列號, 以標識發送出去的數據包中, 哪些是已經被對方收到的。 三次握手的過程即是通信雙方相互告知序列號起始值, 並確認對方已經收到了序列號起始值的必經步驟。
如果只是兩次握手, 至多隻有連接發起方的起始序列號能被確認, 另一方選擇的序列號則得不到確認
75. OSI 的七層模型都有哪些?
應用層:網絡服務與最終用戶的一個接口。
表示層:數據的表示、安全、壓縮。
會話層:建立、管理、終止會話。
傳輸層:定義傳輸數據的協議端口號,以及流控和差錯校驗。
網絡層:進行邏輯地址尋址,實現不同網絡之間的路徑選擇。
數據鏈路層:建立邏輯連接、進行硬件地址尋址、差錯校驗等功能。
物理層:建立、維護、斷開物理連接。
76. get 和 post 請求有哪些區別?
- GET在瀏覽器回退時是無害的,而POST會再次提交請求。
- GET產生的URL地址可以被Bookmark,而POST不可以。
- GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。
- GET請求只能進行url編碼,而POST支持多種編碼方式。
- GET請求參數會被完整保留在瀏覽器歷史記錄裏,而POST中的參數不會被保留。
- GET請求在URL中傳送的參數是有長度限制的,而POST麼有。
- 對參數的數據類型,GET只接受ASCII字符,而POST沒有限制。
- GET比POST更不安全,因爲參數直接暴露在URL上,所以不能用來傳遞敏感信息。
- GET參數通過URL傳遞,POST放在Request body中。
77.說一下 JSONP 實現原理?
jsonp 即 json+padding,動態創建script標籤,利用script標籤的src屬性可以獲取任何域下的js腳本,通過這個特性(也可以說漏洞),服務器端不在返貨json格式,而是返回一段調用某個函數的js代碼,在src中進行了調用,這樣實現了跨域。
設計模式
78.說一下你熟悉的設計模式?
單例模式
簡單點說,就是一個應用程序中,某個類的實例對象只有一個,你沒有辦法去new,因爲構造器是被private修飾的,一般通過getInstance()的方法來獲取它們的實例。
觀察者模式
對象間一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。
裝飾者模式
對已有的業務邏輯進一步的封裝,使其增加額外的功能,如Java中的IO流就使用了裝飾者模式,用戶在使用的時候,可以任意組裝,達到自己想要的效果。
適配器模式
將兩種完全不同的事物聯繫到一起,就像現實生活中的變壓器。
工廠模式
簡單工廠模式:一個抽象的接口,多個抽象接口的實現類,一個工廠類,用來實例化抽象的接口
工廠方法模式:有四個角色,抽象工廠模式,具體工廠模式,抽象產品模式,具體產品模式。
抽象工廠模式:與工廠方法模式不同的是,工廠方法模式中的工廠只生產單一的產品,而抽象工廠模式中的工廠生產多個產品
代理模式(proxy)
有兩種,靜態代理和動態代理。
79. 簡單工廠和抽象工廠有什麼區別?
簡單工廠模式:
這個模式本身很簡單而且使用在業務較簡單的情況下。一般用於小項目或者具體產品很少擴展的情況
它由三種角色組成:
1. 工廠類角色:這是本模式的核心,含有一定的商業邏輯和判斷邏輯,根據邏輯不同,產生具體的工廠產品。如例子中的Driver類 2. 抽象產品角色:它一般是具體產品繼承的父類或者實現的接口。由接口或者抽象類來實現。如例中的Car接口。 3. 具體產品角色:工廠類所創建的對象就是此角色的實例。在java中由一個具體類實現,如例子中的Benz、Bmw類。\
抽象工廠模式:
它和工廠方法模式的區別就在於需要創建對象的複雜程度上。而且抽象工廠模式是三個裏面最爲抽象、最具一般性的。抽象工廠模式的用意爲:給客戶端提供一個接口,可以創建多個產品族中的產品對象。
抽象工廠模式的各個角色
- 抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。在java中它由抽象類或者接口來實現。
- 具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以創建對應的具體產品的對象。在java中它由具體的類來實現。
- 抽象產品角色:它是具體產品繼承的父類或者是實現的接口。在java中一般有抽象類或者接口來實現
- 具體產品角色:具體工廠角色所創建的對象就是此角色的實例。在java中由具體的類來實現。
Spring / Spring MVC
80.爲什麼要使用 spring?
目的:解決企業應用開發的複雜性
功能:使用基本的JavaBean代替EJB,並提供了更多的企業應用功能
範圍:任何Java應用
簡單來說,Spring是一個輕量級的控制反轉(IoC)和麪向切面(AOP)的容器框架。
輕量
控制反轉
Spring通過一種稱作控制反轉(IoC)的技術促進了松耦合。
面向切面
Spring提供了面向切面編程的豐富支持,允許通過分離應用的業務邏輯與系統級服務進行內聚性的開發
容器
Spring包含並管理應用對象的配置和生命週期,在這個意義上它是一種容器,你可以配置你的每個bean如何被創建——基於一個可配置原型,你的bean可以創建一個單獨的實例或者每次需要時都生成一個新的實例——以及它們是如何相互關聯的。
框架
Spring可以將簡單的組件配置、組合成爲複雜的應用。在Spring中,應用對象被聲明式地組合,典型地是在一個XML文件裏。Spring也提供了很多基礎功能(事務管理、持久化框架集成等等),將應用邏輯的開發留給了你。
所有Spring的這些特徵使你能夠編寫更乾淨、更可管理、並且更易於測試的代碼。它們也爲Spring中的各種模塊提供了基礎支持。
81.解釋一下什麼是 aop?
AOP面向方面編程,可以說是OOP面向對象編程的補充和完善
AOP利用一種稱爲“橫切”的技術,剖解開封裝的對象內部,並將那些影響了多個類的公共行爲封裝到一個可重用模塊,並將其名爲“Aspect”,即方面。
所謂“方面”,簡單地說,就是將那些與業務無關,卻爲業務模塊所共同調用的邏輯或責任封裝起來,便於減少系統的重複代碼,降低模塊間的耦合度,並有利於未來的可操作性和可維護性。
使用“橫切”技術,AOP把軟件系統分爲兩個部分:核心關注點和橫切關注點。業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。橫切關注點的一個特點是,他們經常發生在覈心關注點的多處,而各處都基本相似。比如權限認證、日誌、事務處理。Aop 的作用在於分離系統中的各種關注點,將核心關注點和橫切關注點分離開來。
82. 解釋一下什麼是 ioc?
ioc:Inversionof Control(中文:控制反轉)是 spring 的核心,對於 spring 框架來說,就是由 spring 來負責控制對象的生命週期和對象間的關係。
簡單來說,控制指的是當前對象對內部成員的控制權;控制反轉指的是,這種控制權不由當前對象管理了,由其他(類,第三方容器)來管理。
83.什麼是依賴注入?
在依賴注入中,您不必創建對象,但必須描述如何創建它們。您不是直接在代碼 中將組件和服務連接在一起,而是描述配置文件中哪些組件需要哪些服務。由 IoC 容器將它們裝配在一起。
84. spring 常用的注入方式有哪些?
Spring通過DI(依賴注入)實現IOC(控制反轉),常用的注入方式主要有三種:
- 構造方法注入
- setter注入
- 基於註解的注入
85.spring 中的 bean 是線程安全的嗎?
Spring容器中的Bean是否線程安全,容器本身並沒有提供Bean的線程安全策略,因此可以說spring容器中的Bean本身不具備線程安全的特性,但是具體還是要結合具體scope的Bean去研究。
86.spring 支持幾種 bean 的作用域?
Spring支持如下5種作用域:
- singleton:單例模式,在整個Spring IoC容器中,使用singleton定義的Bean將只有一個實例
- prototype:原型模式,每次通過容器的getBean方法獲取prototype定義的Bean時,都將產生一個新的Bean實例
- request:對於每次HTTP請求,使用request定義的Bean都將產生一個新實例,即每次HTTP請求將會產生不同的Bean實例。只有在Web應用中使用Spring時,該作用域纔有效
- session:對於每次HTTP Session,使用session定義的Bean豆漿產生一個新實例。同樣只有在Web應用中使用Spring時,該作用域纔有效
- globalsession:每個全局的HTTP Session,使用session定義的Bean都將產生一個新實例。典型情況下,僅在使用portlet context的時候有效。同樣只有在Web應用中使用Spring時,該作用域纔有效
比較常用的是singleton和prototype兩種作用域。
87. spring 自動裝配 bean 有哪些方式?
spring中bean裝配有兩種方式:
- 隱式的bean發現機制和自動裝配
- 在java代碼或者XML中進行顯示配置
88.說一下 spring 的事務隔離?
事務隔離級別指的是一個事務對數據的修改與另一個並行的事務的隔離程度,當多個事務同時訪問相同數據時,如果沒有采取必要的隔離機制,就可能發生以下問題:
- 髒讀:一個事務讀到另一個事務未提交的更新數據。
- 幻讀:例如第一個事務對一個表中的數據進行了修改,比如這種修改涉及到表中的“全部數據行”。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入“一行新數據”。那麼,以後就會發生操作第一個事務的用戶發現表中還存在沒有修改的數據行,就好象發生了幻覺一樣。
- 不可重複讀:比方說在同一個事務中先後執行兩條一模一樣的select語句,期間在此次事務中沒有執行過任何DDL語句,但先後得到的結果不一致,這就是不可重複讀。
89.說一下 spring mvc 運行流程?
- 用戶向服務器發送請求,請求被Spring 前端控制Servelt DispatcherServlet捕獲;
- DispatcherServlet對請求URL進行解析,得到請求資源標識符(URI)。然後根據該URI,調用HandlerMapping獲得該Handler配置的所有相關的對象,最後以HandlerExecutionChain對象的形式返回;
- DispatcherServlet 根據獲得的Handler,選擇一個合適的HandlerAdapter;
- 提取Request中的模型數據,填充Handler入參,開始執行Handler(Controller)。 在填充Handler的入參過程中,根據你的配置,Spring將幫你做一些額外的工作:
- Handler執行完成後,向DispatcherServlet 返回一個ModelAndView對象;
- 根據返回的ModelAndView,選擇一個適合的ViewResolver返回給DispatcherServlet ;
- ViewResolver 結合Model和View,來渲染視圖;
- 將渲染結果返回給客戶端。
90.spring mvc 有哪些組件?
Spring MVC的核心組件:
- DispatcherServlet:中央控制器,把請求給轉發到具體的控制類
- Controller:具體處理請求的控制器
- HandlerMapping:映射處理器,負責映射中央處理器轉發給controller時的映射策略
- ModelAndView:服務層返回的數據和視圖層的封裝類
- ViewResolver:視圖解析器,解析具體的視圖
- Interceptors :攔截器,負責攔截我們定義的請求然後做處理工作
91.@RequestMapping 的作用是什麼?
RequestMapping是一個用來處理請求地址映射的註解,可用於類或方法上。用於類上,表示類中的所有響應請求的方法都是以該地址作爲父路徑。
RequestMapping註解有六個屬性,下面我們把她分成三類進行說明。
- value, method:
1. value:指定請求的實際地址,指定的地址可以是URI Template 模式
2. method:指定請求的method類型, GET、POST、PUT、DELETE等;- consumes,produces:
- consumes:指定處理請求的提交內容類型;例如application/json, text/html;
- produces:指定返回的內容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才返回;
- params,headers:
- params: 指定request中必須包含某些參數值是,才讓該方法處理。
- headers:指定request中必須包含某些指定的header值,才能讓該方法處理請求。
92.@Autowired 的作用是什麼?
首先要知道另一個東西,default-autowire,它是在xml文件中進行配置的,可以設置爲byName、byType、constructor和autodetect;比如byName,不用顯式的在bean中寫出依賴的對象,它會自動的匹配其它bean中id名與本bean的set**相同的,並自動裝載。
@Autowired是用在JavaBean中的註解,通過byType形式,用來給指定的字段或方法注入所需的外部資源。
兩者的功能是一樣的,就是能減少或者消除屬性或構造器參數的設置,只是配置地方不一樣而已。
Spring Boot / Spring Cloud
93.什麼是 spring boot?
SpringBoot是一個框架,一種全新的編程規範,他的產生簡化了框架的使用,所謂簡化是指簡化了Spring衆多框架中所需的大量且繁瑣的配置文件,所以 SpringBoot是一個服務於框架的框架,服務範圍是簡化配置文件。
94.爲什麼要用 spring boot?
- Spring Boot使編碼變簡單
- Spring Boot使配置變簡單
- Spring Boot使部署變簡單
- Spring Boot使監控變簡單
- 解決Spring的不足
95.spring boot 核心配置文件是什麼?
Spring Boot提供了兩種常用的配置文件:
properties文件
yml文件
96. spring boot 配置文件有哪幾種類型?它們有什麼區別?
Spring Boot提供了兩種常用的配置文件,分別是properties文件和yml文件。
相對於properties文件而言,yml文件使配置文件結構跟清晰,但也會因爲微不足道的空格而破壞了層級關係。
97.spring boot 有哪些方式可以實現熱部署?
SpringBoot熱部署實現有兩種方式:
①. 使用spring loaded
<build> <plugins> <plugin> <!-- springBoot編譯插件--> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <dependencies> <!-- spring熱部署 --> <!-- 該依賴在此處下載不下來,可以放置在build標籤外部下載完成後再粘貼進plugin中 --> <dependency> <groupId>org.springframework</groupId> <artifactId>springloaded</artifactId> <version>1.2.6.RELEASE</version> </dependency> </dependencies> </plugin> </plugins> </build>
②. 使用spring-boot-devtools
在項目的pom文件中添加依賴:
<!--熱部署jar--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>
然後:使用 shift+ctrl+alt+"/" (IDEA中的快捷鍵) 選擇"Registry" 然後勾選 compiler.automake.allow.when.app.running
98. 什麼是 spring cloud?
Spring Cloud 就是致力於分佈式系統、雲服務的框架
Spring Cloud 是整個 Spring 家族中新的成員,是最近雲服務火爆的必然產物。
Spring Cloud 爲開發人員提供了快速構建分佈式系統中一些常見模式的工具,例如:
- 配置管理
- 服務註冊與發現
- 斷路器
- 智能路由
- 服務間調用
- 負載均衡
- 微代理
- 控制總線
- 一次性令牌
- 全局鎖
- 領導選舉
- 分佈式會話
- 集羣狀態
- 分佈式消息
- …
使用 Spring Cloud 開發人員可以開箱即用的實現這些模式的服務和應用程序。這些服務可以任何環境下運行,包括分佈式環境,也包括開發人員自己的筆記本電腦以及各種託管平臺。
99.spring cloud 斷路器的作用是什麼?
在Spring Cloud中使用了Hystrix 來實現斷路器的功能,斷路器可以防止一個應用程序多次試圖執行一個操作,即很可能失敗,允許它繼續而不等待故障恢復或者浪費 CPU 週期,而它確定該故障是持久的。斷路器模式也使應用程序能夠檢測故障是否已經解決,如果問題似乎已經得到糾正,應用程序可以嘗試調用操作。
斷路器增加了穩定性和靈活性,以一個系統,提供穩定性,而系統從故障中恢復,並儘量減少此故障的對性能的影響。它可以幫助快速地拒絕對一個操作,即很可能失敗,而不是等待操作超時(或者不返回)的請求,以保持系統的響應時間。如果斷路器提高每次改變狀態的時間的事件,該信息可以被用來監測由斷路器保護系統的部件的健康狀況,或以提醒管理員當斷路器跳閘,以在打開狀態。
100. spring cloud 的核心組件有哪些?
①. 服務發現——Netflix Eureka
一個RESTful服務,用來定位運行在AWS地區(Region)中的中間層服務。由兩個組件組成:Eureka服務器和Eureka客戶端。Eureka服務器用作服務註冊服務器。Eureka客戶端是一個java客戶端,用來簡化與服務器的交互、作爲輪詢負載均衡器,並提供服務的故障切換支持。Netflix在其生產環境中使用的是另外的客戶端,它提供基於流量、資源利用率以及出錯狀態的加權負載均衡。
②. 客服端負載均衡——Netflix Ribbon
Ribbon,主要提供客戶側的軟件負載均衡算法。Ribbon客戶端組件提供一系列完善的配置選項,比如連接超時、重試、重試算法等。Ribbon內置可插拔、可定製的負載均衡組件
③. 斷路器——Netflix Hystrix
斷路器可以防止一個應用程序多次試圖執行一個操作,即很可能失敗,允許它繼續而不等待故障恢復或者浪費 CPU 週期,而它確定該故障是持久的。斷路器模式也使應用程序能夠檢測故障是否已經解決。如果問題似乎已經得到糾正,應用程序可以嘗試調用操作。
④. 服務網關——Netflix Zuul
類似nginx,反向代理的功能,不過netflix自己增加了一些配合其他組件的特性。
⑤. 分佈式配置——Spring Cloud Config
這個還是靜態的,得配合Spring Cloud Bus實現動態的配置更新。
Mybatis
101.mybatis 中 #{}和 ${}的區別是什麼?
- #{}是預編譯處理,${}是字符串替換;
- Mybatis在處理#{}時,會將sql中的#{}替換爲?號,調用PreparedStatement的set方法來賦值;
- Mybatis在處理{}替換成變量的值;
- 使用#{}可以有效的防止SQL注入,提高系統安全性。
102.mybatis 有幾種分頁方式?
- 數組分頁
- sql分頁
- 攔截器分頁
- RowBounds分頁
103.mybatis 邏輯分頁和物理分頁的區別是什麼?
物理分頁速度上並不一定快於邏輯分頁,邏輯分頁速度上也並不一定快於物理分頁。
物理分頁總是優於邏輯分頁:沒有必要將屬於數據庫端的壓力加諸到應用端來,就算速度上存在優勢,然而其它性能上的優點足以彌補這個缺點。
104.mybatis 是否支持延遲加載?延遲加載的原理是什麼?
Mybatis僅支持association關聯對象和collection關聯集合對象的延遲加載,association指的就是一對一,collection指的就是一對多查詢。在Mybatis配置文件中,可以配置是否啓用延遲加載lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB創建目標對象的代理對象,當調用目標方法時,進入攔截器方法,比如調用a.getB().getName(),攔截器invoke()方法發現a.getB()是null值,那麼就會單獨發送事先保存好的查詢關聯B對象的sql,把B查詢上來,然後調用a.setB(b),於是a的對象b屬性就有值了,接着完成a.getB().getName()方法的調用。這就是延遲加載的基本原理。
105.說一下 mybatis 的一級緩存和二級緩存?
一級緩存: 基於 PerpetualCache 的 HashMap 本地緩存,其存儲作用域爲 Session,當 Session flush 或 close 之後,該 Session 中的所有 Cache 就將清空,默認打開一級緩存。
二級緩存與一級緩存其機制相同,默認也是採用 PerpetualCache,HashMap 存儲,不同在於其存儲作用域爲 Mapper,並且可自定義存儲源,如 Ehcache。默認不打開二級緩存,要開啓二級緩存,使用二級緩存屬性類需要實現Serializable序列化接口,可在它的映射文件中配置 ;
對於緩存數據更新機制,當某一個作用域操作後,默認該作用域下所有 select 中的緩存將被 clear。
106.mybatis 和 hibernate 的區別有哪些?
Mybatis和hibernate不同,它不完全是一個ORM框架,因爲MyBatis需要程序員自己編寫Sql語句
Mybatis直接編寫原生態sql,可以嚴格控制sql執行性能,靈活度高,非常適合對關係數據模型要求不高的軟件開發,因爲這類軟件需求變化頻繁,一但需求變化要求迅速輸出成果。但是靈活的前提是mybatis無法做到數據庫無關性,如果需要實現支持多種數據庫的軟件,則需要自定義多套sql映射文件,工作量大。
Hibernate對象/關係映射能力強,數據庫無關性好,對於關係模型要求高的軟件,如果用hibernate開發可以節省很多代碼,提高效率。
107.mybatis 有哪些執行器(Executor)?
Mybatis有三種基本的執行器(Executor):
- SimpleExecutor:每執行一次update或select,就開啓一個Statement對象,用完立刻關閉Statement對象。
- ReuseExecutor:執行update或select,以sql作爲key查找Statement對象,存在就使用,不存在就創建,用完後,不關閉Statement對象,而是放置於Map內,供下一次使用。簡言之,就是重複使用Statement對象。
- BatchExecutor:執行update,將所有sql都添加到批處理中,等待統一執行,它緩存了多個Statement對象,每個Statement對象都是addBatch()完畢後,等待逐一執行executeBatch()批處理。與JDBC批處理相同。
108.mybatis 分頁插件的實現原理是什麼?
分頁插件的基本原理是使用Mybatis提供的插件接口,實現自定義插件,在插件的攔截方法內攔截待執行的sql,然後重寫sql,根據dialect方言,添加對應的物理分頁語句和物理分頁參數。
RabbitMQ
109.rabbitmq 的使用場景有哪些?
- 跨系統的異步通信,所有需要異步交互的地方都可以使用消息隊列。就像我們除了打電話(同步)以外,還需要發短信,發電子郵件(異步)的通訊方式。
- 多個應用之間的耦合,由於消息是平臺無關和語言無關的,而且語義上也不再是函數調用,因此更適合作爲多個應用之間的松耦合的接口。基於消息隊列的耦合,不需要發送方和接收方同時在線。在企業應用集成(EAI)中,文件傳輸,共享數據庫,消息隊列,遠程過程調用都可以作爲集成的方法。
- 應用內的同步變異步,比如訂單處理,就可以由前端應用將訂單信息放到隊列,後端應用從隊列裏依次獲得消息處理,高峯時的大量訂單可以積壓在隊列裏慢慢處理掉。由於同步通常意味着阻塞,而大量線程的阻塞會降低計算機的性能。
- 消息驅動的架構(EDA),系統分解爲消息隊列,和消息製造者和消息消費者,一個處理流程可以根據需要拆成多個階段(Stage),階段之間用隊列連接起來,前一個階段處理的結果放入隊列,後一個階段從隊列中獲取消息繼續處理。
- 應用需要更靈活的耦合方式,如發佈訂閱,比如可以指定路由規則。
- 跨局域網,甚至跨城市的通訊(CDN行業),比如北京機房與廣州機房的應用程序的通信。
110. rabbitmq 有哪些重要的角色?
RabbitMQ 中重要的角色有:生產者、消費者和代理:
- 生產者:消息的創建者,負責創建和推送數據到消息服務器;
- 消費者:消息的接收方,用於處理數據和確認消息;
- 代理:就是 RabbitMQ 本身,用於扮演“快遞”的角色,本身不生產消息,只是扮演“快遞”的角色。
111.rabbitmq 有哪些重要的組件?
- ConnectionFactory(連接管理器):應用程序與Rabbit之間建立連接的管理器,程序代碼中使用。
- Channel(信道):消息推送使用的通道。
- Exchange(交換器):用於接受、分配消息。
- Queue(隊列):用於存儲生產者的消息。
- RoutingKey(路由鍵):用於把生成者的數據分配到交換器上。
- BindingKey(綁定鍵):用於把交換器的消息綁定到隊列上。
112.rabbitmq 中 vhost 的作用是什麼?
vhost 可以理解爲虛擬 broker ,即 mini-RabbitMQ server。其內部均含有獨立的 queue、exchange 和 binding 等,但最最重要的是,其擁有獨立的權限系統,可以做到 vhost 範圍的用戶控制。當然,從 RabbitMQ 的全局角度,vhost 可以作爲不同權限隔離的手段
113**. rabbitmq 的消息是怎麼發送的?**
首先客戶端必須連接到 RabbitMQ 服務器才能發佈和消費消息,客戶端和 rabbit server 之間會創建一個 tcp 連接,一旦 tcp 打開並通過了認證(認證就是你發送給 rabbit 服務器的用戶名和密碼),你的客戶端和 RabbitMQ 就創建了一條 amqp 信道(channel),信道是創建在“真實” tcp 上的虛擬連接,amqp 命令都是通過信道發送出去的,每個信道都會有一個唯一的 id,不論是發佈消息,訂閱隊列都是通過這個信道完成的。
114.rabbitmq 怎麼保證消息的穩定性?
提供了事務的功能。
通過將 channel 設置爲 confirm(確認)模式。
115. rabbitmq 怎麼避免消息丟失?
- 消息持久化
- ACK確認機制
- 設置集羣鏡像模式
- 消息補償機制
116.要保證消息持久化成功的條件有哪些?
- 聲明隊列必須設置持久化 durable 設置爲 true.
- 消息推送投遞模式必須設置持久化,deliveryMode 設置爲 2(持久)。
- 消息已經到達持久化交換器。
- 消息已經到達持久化隊列。
以上四個條件都滿足才能保證消息持久化成功。
117.rabbitmq 持久化有什麼缺點?
持久化的缺地就是降低了服務器的吞吐量,因爲使用的是磁盤而非內存存儲,從而降低了吞吐量。可儘量使用 ssd 硬盤來緩解吞吐量的問題。
118.rabbitmq 有幾種廣播類型?
三種廣播模式:
- fanout: 所有bind到此exchange的queue都可以接收消息
- direct: 通過routingKey和exchange決定的那個唯一的queue可以接收消息;
- topic:所有符合routingKey(此時可以是一個表達式)的routingKey所bind的queue可以接收消息;
119.rabbitmq 怎麼實現延遲消息隊列?
- 通過消息過期後進入死信交換器,再由交換器轉發到延遲消費隊列,實現延遲功能;
- 使用 RabbitMQ-delayed-message-exchange 插件實現延遲功能。
120.rabbitmq 集羣有什麼用?
集羣主要有以下兩個用途:
- 高可用:某個服務器出現問題,整個 RabbitMQ 還可以繼續使用;
- 高容量:集羣可以承載更多的消息量。
121.rabbitmq 節點的類型有哪些?
- 磁盤節點:消息會存儲到磁盤。
- 內存節點:消息都存儲在內存中,重啓服務器消息丟失,性能高於磁盤類型。
122.rabbitmq 集羣搭建需要注意哪些問題?
- 各節點之間使用“–link”連接,此屬性不能忽略。
- 各節點使用的 erlang cookie 值必須相同,此值相當於“祕鑰”的功能,用於各節點的認證
- 整個集羣中必須包含一個磁盤節點。
123.rabbitmq 每個節點是其他節點的完整拷貝嗎?爲什麼?
不是,原因有以下兩個:
- 存儲空間的考慮:如果每個節點都擁有所有隊列的完全拷貝,這樣新增節點不但沒有新增存儲空間,反而增加了更多的冗餘數據;
- 性能的考慮:如果每條消息都需要完整拷貝到每一個集羣節點,那新增節點並沒有提升處理消息的能力,最多是保持和單節點相同的性能甚至是更糟。
124.rabbitmq 集羣中唯一一個磁盤節點崩潰了會發生什麼情況?
如果唯一磁盤的磁盤節點崩潰了,不能進行以下操作:
- 不能創建隊列
- 不能創建交換器
- 不能創建綁定
- 不能添加用戶
- 不能更改權限
- 不能添加和刪除集羣節點
唯一磁盤節點崩潰了,集羣是可以保持運行的,但你不能更改任何東西。
125. rabbitmq 對集羣節點停止順序有要求嗎?
RabbitMQ 對集羣的停止的順序是有要求的,應該先關閉內存節點,最後再關閉磁盤節點。如果順序恰好相反的話,可能會造成消息的丟失。
Kafka
126.kafka 可以脫離 zookeeper 單獨使用嗎?爲什麼?
kafka 不能脫離 zookeeper 單獨使用,因爲 kafka 使用 zookeeper 管理和協調 kafka 的節點服務器。
127.kafka 有幾種數據保留的策略?
kafka 有兩種數據保存策略:按照過期時間保留和按照存儲的消息大小保留。
128. kafka 同時設置了 7 天和 10G 清除數據,到第五天的時候消息達到了 10G,這個時候 kafka 將如何處理?
這個時候 kafka 會執行數據清除工作,時間和大小不論那個滿足條件,都會清空數據。
129.什麼情況會導致 kafka 運行變慢?
- cpu 性能瓶頸
- 磁盤讀寫瓶頸
- 網絡瓶頸
130.使用 kafka 集羣需要注意什麼?
- 集羣的數量不是越多越好,最好不要超過 7 個,因爲節點越多,消息複製需要的時間就越長,整個羣組的吞吐量就越低。
- 集羣數量最好是單數,因爲超過一半故障集羣就不能用了,設置爲單數容錯率更高。
Zookeeper
131.zookeeper 是什麼?
zookeeper 是一個分佈式的,開放源碼的分佈式應用程序協調服務,是 google chubby 的開源實現,是 hadoop 和 hbase 的重要組件。它是一個爲分佈式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分佈式同步、組服務等。
132.zookeeper 都有哪些功能?
- 集羣管理:監控節點存活狀態、運行請求等。
- 主節點選舉:主節點掛掉了之後可以從備用的節點開始新一輪選主,主節點選舉說的就是這個選舉的過程,使用 zookeeper 可以協助完成這個過程。
- 分佈式鎖:zookeeper 提供兩種鎖:獨佔鎖、共享鎖。獨佔鎖即一次只能有一個線程使用資源,共享鎖是讀鎖共享,讀寫互斥,即可以有多線線程同時讀同一個資源,如果要使用寫鎖也只能有一個線程使用。zookeeper可以對分佈式鎖進行控制。
- 命名服務:在分佈式系統中,通過使用命名服務,客戶端應用能夠根據指定名字來獲取資源或服務的地址,提供者等信息。
133.zookeeper 有幾種部署模式?
zookeeper 有三種部署模式:
- 單機部署:一臺集羣上運行;
- 集羣部署:多臺集羣運行;
- 僞集羣部署:一臺集羣啓動多個 zookeeper 實例運行。
134.zookeeper 怎麼保證主從節點的狀態同步?
zookeeper 的核心是原子廣播,這個機制保證了各個 server 之間的同步。實現這個機制的協議叫做 zab 協議。 zab 協議有兩種模式,分別是恢復模式(選主)和廣播模式(同步)。當服務啓動或者在領導者崩潰後,zab 就進入了恢復模式,當領導者被選舉出來,且大多數 server 完成了和 leader 的狀態同步以後,恢復模式就結束了。狀態同步保證了 leader 和 server 具有相同的系統狀態。
135.集羣中爲什麼要有主節點?
在分佈式環境中,有些業務邏輯只需要集羣中的某一臺機器進行執行,其他的機器可以共享這個結果,這樣可以大大減少重複計算,提高性能,所以就需要主節點。
136.集羣中有 3 臺服務器,其中一個節點宕機,這個時候 zookeeper 還可以使用嗎?
可以繼續使用,單數服務器只要沒超過一半的服務器宕機就可以繼續使用。
137.說一下 zookeeper 的通知機制?
客戶端端會對某個 znode 建立一個 watcher 事件,當該 znode 發生變化時,這些客戶端會收到 zookeeper 的通知,然後客戶端可以根據 znode 變化來做出業務上的改變。
MySql
138.數據庫的三範式是什麼?
第一範式:強調的是列的原子性,即數據庫表的每一列都是不可分割的原子數據項。
第二範式:要求實體的屬性完全依賴於主關鍵字。所謂完全依賴是指不能存在僅依賴主關鍵字一部分的屬性。
第三範式:任何非主屬性不依賴於其它非主屬性。
139. 如何獲取當前數據庫版本?
使用 select version() 獲取當前 MySQL 數據庫版本。
140.說一下 ACID 是什麼?
- Atomicity(原子性):一個事務(transaction)中的所有操作,或者全部完成,或者全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被恢復(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。即,事務不可分割、不可約簡。
- Consistency(一致性):在事務開始之前和事務結束以後,數據庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設約束、觸發器、級聯回滾等。
- Isolation(隔離性):數據庫允許多個併發事務同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事務併發執行時由於交叉執行而導致數據的不一致。事務隔離分爲不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和串行化(Serializable)。
- Durability(持久性):事務處理結束後,對數據的修改就是永久的,即便系統故障也不會丟失。
141.char 和 varchar 的區別是什麼?
char(n) :固定長度類型,比如訂閱 char(10),當你輸入"abc"三個字符的時候,它們佔的空間還是 10 個字節,其他 7 個是空字節。
chat 優點:效率高;缺點:佔用空間;適用場景:存儲密碼的 md5 值,固定長度的,使用 char 非常合適。
varchar(n) :可變長度,存儲的值是每個值佔用的字節再加上一個用來記錄其長度的字節的長度。
所以,從空間上考慮 varcahr 比較合適;從效率上考慮 char 比較合適,二者使用需要權衡。
142.float 和 double 的區別是什麼?
float 最多可以存儲 8 位的十進制數,並在內存中佔 4 字節。
double 最可可以存儲 16 位的十進制數,並在內存中佔 8 字節。
143.mysql 的內連接、左連接、右連接有什麼區別?
內連接關鍵字:inner join;左連接:left join;右連接:right join。
內連接是把匹配的關聯數據顯示出來;左連接是左邊的表全部顯示出來,右邊的表顯示出符合條件的數據;右連接正好相反。
144.mysql 索引是怎麼實現的?
索引是滿足某種特定查找算法的數據結構,而這些數據結構會以某種方式指向數據,從而實現高效查找數據。
具體來說 MySQL 中的索引,不同的數據引擎實現有所不同,但目前主流的數據庫引擎的索引都是 B+ 樹實現的,B+ 樹的搜索效率,可以到達二分法的性能,找到數據區域之後就找到了完整的數據結構了,所有索引的性能也是更好的。
145.怎麼驗證 mysql 的索引是否滿足需求?
使用 explain 查看 SQL 是如何執行查詢語句的,從而分析你的索引是否滿足需求。
explain 語法:explain select * from table where type=1。
146.說一下數據庫的事務隔離?
MySQL 的事務隔離是在 MySQL. ini 配置文件裏添加的,在文件的最後添加:transaction-isolation = REPEATABLE-READ
可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE。
- READ-UNCOMMITTED:未提交讀,最低隔離級別、事務未提交前,就可被其他事務讀取(會出現幻讀、髒讀、不可重複讀)。
- READ-COMMITTED:提交讀,一個事務提交後才能被其他事務讀取到(會造成幻讀、不可重複讀)。
- REPEATABLE-READ:可重複讀,默認級別,保證多次讀取同一個數據時,其值都和事務開始時候的內容是一致,禁止讀取到別的事務未提交的數據(會造成幻讀)。
- SERIALIZABLE:序列化,代價最高最可靠的隔離級別,該隔離級別能防止髒讀、不可重複讀、幻讀。
髒讀 :表示一個事務能夠讀取另一個事務中還未提交的數據。比如,某個事務嘗試插入記錄 A,此時該事務還未提交,然後另一個事務嘗試讀取到了記錄 A。
不可重複讀 :是指在一個事務內,多次讀同一數據。
幻讀 :指同一個事務內多次查詢返回的結果集不一樣。比如同一個事務 A 第一次查詢時候有 n 條記錄,但是第二次同等條件下查詢卻有 n+1 條記錄,這就好像產生了幻覺。發生幻讀的原因也是另外一個事務新增或者刪除或者修改了第一個事務結果集裏面的數據,同一個記錄的數據內容被修改了,所有數據行的記錄就變多或者變少了。
147.說一下 mysql 常用的引擎?
InnoDB 引擎:InnoDB 引擎提供了對數據庫 acid 事務的支持,並且還提供了行級鎖和外鍵的約束,它的設計的目標就是處理大數據容量的數據庫系統。MySQL 運行的時候,InnoDB 會在內存中建立緩衝池,用於緩衝數據和索引。但是該引擎是不支持全文搜索,同時啓動也比較的慢,它是不會保存表的行數的,所以當進行 select count(*) from table 指令的時候,需要進行掃描全表。由於鎖的粒度小,寫操作是不會鎖定全表的,所以在併發度較高的場景下使用會提升效率的。
MyIASM 引擎:MySQL 的默認引擎,但不提供事務的支持,也不支持行級鎖和外鍵。因此當執行插入和更新語句時,即執行寫操作的時候需要鎖定這個表,所以會導致效率會降低。不過和 InnoDB 不同的是,MyIASM 引擎是保存了表的行數,於是當進行 select count(*) from table 語句時,可以直接的讀取已經保存的值而不需要進行掃描全表。所以,如果表的讀操作遠遠多於寫操作時,並且不需要事務的支持的,可以將 MyIASM 作爲數據庫引擎的首選。
148.說一下 mysql 的行鎖和表鎖?
MyISAM 只支持表鎖,InnoDB 支持表鎖和行鎖,默認爲行鎖。
- 表級鎖:開銷小,加鎖快,不會出現死鎖。鎖定粒度大,發生鎖衝突的概率最高,併發量最低。
- 行級鎖:開銷大,加鎖慢,會出現死鎖。鎖力度小,發生鎖衝突的概率小,併發度最高。
149.說一下樂觀鎖和悲觀鎖?
- 樂觀鎖:每次去拿數據的時候都認爲別人不會修改,所以不會上鎖,但是在提交更新的時候會判斷一下在此期間別人有沒有去更新這個數據。
- 悲觀鎖:每次去拿數據的時候都認爲別人會修改,所以每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻止,直到這個鎖被釋放。
數據庫的樂觀鎖需要自己實現,在表裏面添加一個 version 字段,每次修改成功值加 1,這樣每次修改的時候先對比一下,自己擁有的 version 和數據庫現在的 version 是否一致,如果不一致就不修改,這樣就實現了樂觀鎖。
150.mysql 問題排查都有哪些手段?
- 使用 show processlist 命令查看當前所有連接信息。
- 使用 explain 命令查詢 SQL 語句執行計劃。
- 開啓慢查詢日誌,查看慢查詢的 SQL。
151.如何做 mysql 的性能優化?
- 爲搜索字段創建索引。
- 避免使用 select *,列出需要查詢的字段。
- 垂直分割分表。
- 選擇正確的存儲引擎。
Redis
152. redis 是什麼?都有哪些使用場景?
Redis是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。
Redis 使用場景:
- 數據高併發的讀寫
- 海量數據的讀寫
- 對擴展性要求高的數據
153. redis 有哪些功能?
- 數據緩存功能
- 分佈式鎖的功能
- 支持數據持久化
- 支持事務
- 支持消息隊列
154.redis 和 memecache 有什麼區別?
- memcached所有的值均是簡單的字符串,redis作爲其替代者,支持更爲豐富的數據類型
- redis的速度比memcached快很多
- redis可以持久化其數據
155.redis 爲什麼是單線程的?
因爲 cpu 不是 Redis 的瓶頸,Redis 的瓶頸最有可能是機器內存或者網絡帶寬。既然單線程容易實現,而且 cpu 又不會成爲瓶頸,那就順理成章地採用單線程的方案了。
關於 Redis 的性能,官方網站也有,普通筆記本輕鬆處理每秒幾十萬的請求。
而且單線程並不代表就慢 nginx 和 nodejs 也都是高性能單線程的代表。
156.什麼是緩存穿透?怎麼解決?
緩存穿透:指查詢一個一定不存在的數據,由於緩存是不命中時需要從數據庫查詢,查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到數據庫去查詢,造成緩存穿透。
解決方案:最簡單粗暴的方法如果一個查詢返回的數據爲空,我們就把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。
157. redis 支持的數據類型有哪些?
string、list、hash、set、zset。
158. redis 支持的 java 客戶端都有哪些?
Redisson、Jedis、lettuce等等,官方推薦使用Redisson。
159.jedis 和 redisson 有哪些區別?
Jedis是Redis的Java實現的客戶端,其API提供了比較全面的Redis命令的支持。
Redisson實現了分佈式和可擴展的Java數據結構,和Jedis相比,功能較爲簡單,不支持字符串操作,不支持排序、事務、管道、分區等Redis特性。Redisson的宗旨是促進使用者對Redis的關注分離,從而讓使用者能夠將精力更集中地放在處理業務邏輯上。
160.怎麼保證緩存和數據庫數據的一致性?
合理設置緩存的過期時間。
新增、更改、刪除數據庫操作時同步更新 Redis,可以使用事物機制來保證數據的一致性。
161. redis 持久化有幾種方式?
Redis 的持久化有兩種方式,或者說有兩種策略:
- RDB(Redis Database):指定的時間間隔能對你的數據進行快照存儲。
- AOF(Append Only File):每一個收到的寫命令都通過write函數追加到文件中
162. redis 怎麼實現分佈式鎖?
Redis 分佈式鎖其實就是在系統裏面佔一個“坑”,其他程序也要佔“坑”的時候,佔用成功了就可以繼續執行,失敗了就只能放棄或稍後重試。
佔坑一般使用 setnx(set if not exists)指令,只允許被一個程序佔有,使用完調用 del 釋放鎖。
163.redis 分佈式鎖有什麼缺陷?
Redis 分佈式鎖不能解決超時的問題,分佈式鎖有一個超時時間,程序的執行如果超出了鎖的超時時間就會出現問題。
164. redis 如何做內存優化?
儘可能使用散列表(hashes),散列表(是說散列表裏面存儲的數少)使用的內存非常小,所以你應該儘可能的將你的數據模型抽象到一個散列表裏面。
比如你的web系統中有一個用戶對象,不要爲這個用戶的名稱,姓氏,郵箱,密碼設置單獨的key,而是應該把這個用戶的所有信息存儲到一張散列表裏面。
165.redis 淘汰策略有哪些?
- volatile-lru:從已設置過期時間的數據集(server. db[i]. expires)中挑選最近最少使用的數據淘汰。
- volatile-lru:從已設置過期時間的數據集(server. db[i]. expires)中挑選最近最少使用的數據淘汰。
- volatile-ttl:從已設置過期時間的數據集(server. db[i]. expires)中挑選將要過期的數據淘汰。
- volatile-random:從已設置過期時間的數據集(server. db[i]. expires)中任意選擇數據淘汰。
- allkeys-lru:從數據集(server. db[i]. dict)中挑選最近最少使用的數據淘汰。
- allkeys-random:從數據集(server. db[i]. dict)中任意選擇數據淘汰。
- no-enviction(驅逐):禁止驅逐數據。
166. redis 常見的性能問題有哪些?該如何解決?
主服務器寫內存快照,會阻塞主線程的工作,當快照比較大時對性能影響是非常大的,會間斷性暫停服務,所以主服務器最好不要寫內存快照。
Redis 主從複製的性能問題,爲了主從複製的速度和連接的穩定性,主從庫最好在同一個局域網內。
轉載於:https://mp.weixin.qq.com/s/AK99g04yJRXQFQcx1ak0fg