這是從網上看到的一套java面試題, 答案只是一個大概, 另外題目質量良莠不齊, 斟酌參考(JVM的部分暫時沒有答案)html
答: JDK(Java Development Kit)是java開發工具包, 是針對開發人員提供的一套開發環境, 其中包含了jre(程序運行環境,標準類庫class文件)以及編譯器javac等一系列工具. JRE(Java Runtime Environment)是Java運行時環境, 針對生產環境發佈, 其中包含了JVM虛擬機以及標準類庫的class文件.前端
另外, JVM(Java Virtual Machine)Java虛擬機, 將class字節碼指令翻譯爲機器指令, 是跨平臺的核心.java
答: == 能夠用於值類型和對象類型, 可用於斷定兩個值是否相等. 當用於引用類型時, 用來斷定兩個對象地址, 便是否指向相同的內存空間. equals()方法的Object的默認實現使用==比較, 也就是說默認就是比較對象地址是否相等, 但類庫中的不少類, 包括包裝類型, String等均重寫了該方法. equals用來比較對象內容是否相等, 對於自定義類型, 能夠重寫此方法實現對象自定義的比較邏輯, 這個邏輯通常要求比較嚴謹複雜,因此同時也要重寫hashCode()方法,畢竟若是能在實現中先使用hashCode比較可能會對性能有積極影響.mysql
答: 不對! hashCode()相同, 由於可能存在hash碰撞, 也可能致使不一樣的對象計算出相同的hash值. 另外, hashCode()和equals()方法都是Object對象的方法, 自定義類型可能會覆蓋也可能不覆蓋這兩個方法, 因此說他們必定爲true是不對的. 通常而言, 若是equals()方法返回true, 則hashCode()的值相同, 反之不必定成立.程序員
答: final 能夠修飾域變量, 方法, 類. 修飾的域變量的值不能被從新賦值, 修飾的方法不能在子類中被重寫, 修飾的類不能被繼承. final是保證程序不被惡意篡改的手段.web
final常常是static一塊兒使用.
final的優勢: 1.提示了性能, jvm和程序會緩存變量, 方法是靜態綁定的; 2. 安全地在多線程環境下共享變量,沒有多餘開銷;
final變量通常要大寫, 局部變量須要聲明時就賦值, 但域變量能夠在構造函數, 初始化塊兒內賦值.面試
答: 1 就近舍入也叫銀行家舍入. 方法是原值+0.5後下取整.ajax
答: 不屬於! 基本數據類型只有8種. boolean byte short int long float double char . String是引用類型, 並將其設置爲final, String的具體字符串值在常量池中存在.redis
答: 除了基本的String, 還有StringBuidler和StringBuffer. String作字符串操做時效率過低, 由於其不可變性, 可能會有大量對象建立而佔用大量內存. 然後二者用來處理字符串對象, 不一樣之處在於StringBuffer時線程安全的, StringBuilder爲了效率考慮線程不安全.算法
答: 不同, 字符串存在常量池中, 若是常量池中不存在, 則建立; 若是使用new 建立, 則須要在堆上建立String對象, 並在常量池中建立字符串"i"(若是不存在的話).
答: 有若干方法, 最簡單的是使用StringBuilder#reverse()方法.
另外還有,(1).二分遞歸;(2),charAt()拼接字符串;(3)數組反轉拼接;(4)數組字符首尾替換;(5)使用Stack
答:
charAt(); compareTo();compareToIgnoreCase();concat();contains();static copyValueOf();endsWith();equals();equalsIgnoreCase(); static format(); getBytes();getChars(); indexOf(); isEmpty(); lastIndexOf();length();matchs();replace();replaceAll();replaceFirst();spilit();startsWith();subString();toCharArray();toLowerCase();toUpperCase();trim();valueOf();
;
答: 抽象類中的抽象方法不是必須的, 但抽象方法必定在抽象類中; 即便沒有抽象方法的抽象類也不能被實例化.
答: (1).抽象類不能被實例化;(2).抽象方法用abstract修飾且沒有實現;(3).有抽象方法的類必須聲明爲抽象類;(4).抽象類的子類若是不是抽象類就必須實現抽象方法;(5).抽象方法不能爲static;(6).抽象類能夠有構造函數;
答: 不能! final的類不能被其餘類繼承, 而抽象類中的方法必須被子類實現, 自己有衝突. 若是在idea中聲明, 編譯器會報非法組合的修飾符.
答: (1).本質上抽象類是類Class,接口是徹底不一樣的一種類型Interface;(2)接口不能有構造函數,抽象類能夠有;(3).接口中的方法無修飾符(但其是public),接口中的方法能夠被普通方法的修飾符修飾(抽象方法除外,不能是private,static);(4)接口能夠被多繼承, 抽象類只能單繼承;(5)接口中的屬性默認是static final的,抽象類能夠是任意;(6)1.8以前接口方法必須被實現類實現, 抽象類的抽象方法必須被子類實現,1.8以後接口能夠有默認實現了;(7)抽象類能夠有main方法,並能夠執行;
答: 字節流和字符流; 輸入流和輸出流;緩衝流和非緩衝流;
答: BIO:阻塞IO; NIO: new io 又叫非阻塞IO, 多路複用器seletctor; AIO : 異步IO. 參看:以Java的視角來聊聊BIO、NIO與AIO的區別
BIO 是同步阻塞IO, 讀寫操做由單獨的線程完成, 若是出現資源等待則線程被阻塞,操做系統級別來講會出現線程上下文切換, 致使性能開銷, 因此BIO適合少許讀寫操做, 不適合大量併發操做如web環境.
NIO 是同步非阻塞IO, NIO基於事件驅動, 目的就是解決BIO的高併發問題. NIO採用多路複用機制, 當有流須要讀寫時才使用線程處理, 不然不作操做.NIO抽象出Channal和Buffer的概念, 以及Selector, 而不針對Stream直接操做, 而是使用Buffer和Channel, Buffer中使用DirectByteBuffer性能更快, 由於這個類不使用java堆,直接使用系統接口申請內存,減小了數據複製轉移等操做的開銷,但也容易致使OOM. Selector多路複用的基礎類, 單線程處理多個Channel
AIO 是異步非阻塞IO, java7發佈. 是在數據準備好以後通知線程處理的方式, 而不是NIO的輪訓, AIO是真正的同步, 底層調用了系統級別的API實現.
答:
canExecute();canRead();canWrite();compareTo();createNewFile();createTempFile();delete();deleteOnExit();equals();getAbsoluteFile();getFreeSpace();getName();getParent();getParentFile();getPath();isAbsolute();isDirectory();isFile();isHidden();lastModified();length();list();listFiles(),listRoots();mkdir();mkdirs();renameTo();setExecutable();setLastModified();setReadable();setWritable();toURI();
答:
Array,String
,java.util
包下面的Collection,List,ArrayList,LinkedList,Vector,Stack,Map,HashMap,WeakHashMap,LinkedHashMap,HashTable,TreeTable,Set,HashSet,TreeSet,LinkedSet,Queue,
對應的併發容器類,阻塞容器類.
答: Collection 是集合接口,提供了對集合對象最基本的通用接口方法. 定義了集合最大化統一操做方式. Collections 是一個工具類, 包含了各類集合操做的靜態方法, 這個類不能實例化, 只是一個工具類, 相似Arrays.
答: List是有序集合,元素能夠重複, Set的元素不能重複,只容許一個null元素; List和Set都繼承自Collection; Map是鍵值對,鍵能夠做爲索引來查找值, 能夠有多個null值,但只有一個null鍵.
答: 簡單的說, HashTable 是線程安全的, HashMap 是線程不安全的, 也正由於此, HashMap的效率更高. 從內部實現看, HashMap和HashTable實現上幾乎徹底相同, 只不過HashTable是用synchronized的. HashTable不容許null作鍵, HashMap容許null作鍵, 但僅容許一個.ConcurrentHashMap是HashTable的替代, 比後者具備更好擴展性.
答: 最大的區別是 TreeMap 是有序的, HashMap 並不能保證元素的順序. HashMap 繼承了AbstractMap,TreeMap繼承了SortedMap. HashMap適用於Map中插入,刪除和定位. TreeMap適用於按天然順序和自定義順序遍歷(key).
答: 基於1.8. HashMap的內部實現爲一個數組, 每一個元素稱爲桶bucket, 每一個元素爲Node, 包含key, value, Node類型的next, 還有個hash值. HashMap的初始容量是16, 默認填充因子是0.75, 當容量不夠時其擴容按N*2擴容. 當桶中元素不大於8時數據結構是個列表, 當大因而轉化爲紅黑樹, 當紅黑樹元素小於6時退化爲列表.
hash的方法和定位, 先對hash值計算, 方法是高16位與低16位異或運算, 而後用容量n-1與hash結果與運算, 算出下標.
resize 的處理, 由於容量都是2的N次冪, 因此調整size的時候能夠原位不變, 在高位填充隨機的0或1. 即移動一個2次冪的位置. resize能夠均勻的把衝突的節點分佈到新的桶中了.
答: HashSet 基於 HashMap實現. 但僅僅使用key來實現各類特性. 內部定義了一個假值用來操做.
答: ArrayList隨機訪問比較高效, LinkedList更適合作增長刪除修改操做. 分開來講, ArrayList是以數組的方式實現, 能經過索引快速定位. LinkedList是鏈表, 每一個元素保存了前一節點和後一節點的引用.
答: List#toArray()方法將List轉爲數組, new ArrayList(Arrays.asList()) 方法將數組轉爲List.
答: 都基於數組實現, Vector出現較早,提供了線程安全性, ArrayList效率更高. Vector默認增加爲原容量2倍, ArrayList默認增加爲原容量1.5倍+1.
答: Array是數組, ArrayList是列表實現了List接口. ArrayList能夠動態擴容, Array的容量是固定的.
答: 當隊列爲空時poll()會返回null, remove()則拋出異常.
答: HashTable, Vector,Stack, concurrent包下面的集合類, ConcurrentHashMap,ConcurrentSkipListMap、ConcurrentSkipListSet、ConcurrentLinkedQueue、ConcurrentLinkedDeque等, CopyOnWriteArrayList, CopyOnWriteArraySet.
答: Iterator是個接口, 實現了該接口的類通常是集合類, 可以遍歷集合中的元素. 迭代器是一種設計模式. Java中的Iterator只能單向移動, 包含的方法next(),hasNext(),remove(). 迭代器取代了原來的Enumeration接口.
答:
while(iterator.hasNext()){...}
Iterator的特色是更加安全, 由於它能夠確保在遍歷的集合元素被修改後拋出ConcurrentModiicationException
答: ListIterator 擴展了 Iterator. 固然Iterator有的功能ListIterator就有. 但ListIterator新增了一些額外的功能, 好比添加,替換獲取前面或後面元素的索引位置. 另外, ListIterator是雙向的.
答: 可使用Collections類的靜態方法unmodifiableCollection()方法建立只讀集合. 任何改變集合的操做都將拋出
java.lang.UnsupportedOperationException
答: 並行是針對多核CPU的, 指多個任務能夠同時分別在各自CPU上運行; 併發是指多個線程爭奪同一個CPU資源(時間片), 存在上下文切換. CPU一個時間點只能處理一個任務.
答: 線程是系統調度資源的最小單位, 進程是系統分配資源的最小單位, 一個程序包含至少一個進程, 一個進程包含至少一個線程.
答: 守護線程是針對用戶線程的, 用戶線程是程序啓動的線程, 守護線程通常是有JVM啓動, 但也不必定. 對於任何線程, 都可以在啓動前調用setDeamon(true)方法設置爲守護線程.
答: Thread, Runnable, Callable
答: callable有返回值, runnable沒有.
答: NEW, RUNABLE, TERMINATED, BLOCKED, WAITING,TIMED_WAITING
答: (1).sleep()是線程方法,wait()是Object的方法;(2)sleep()超時後會繼續執行, wait()須要notify()或notifyAll()喚醒;(3)sleep()不放棄對象鎖,wait()會釋放對象鎖.
答: nodify()喚醒一個等待鎖的線程, 由JVM決定是哪一個, nodifyAll()會通知全部等待鎖的線程, 這些線程會爭奪對象鎖, 搶到的持有鎖並繼續執行, 其餘的繼續等待通知.
答: run()定義了線程執行的邏輯, start()方法用來啓動線程.run()能夠執行屢次.
答:
java.util.concurrent.Executors
方法下的幾個靜態建立線程池的方法,newFixedThreadPool(), newWorkStealingPool(),newSingleThreadExecutor(),newCachedThreadPool(),newSingleThreadScheduledExecutor(),newScheduledThreadPool()
public ThreadPoolExecutor(int corePoolSize, //核心線程數 int maximumPoolSize, //最大線程數, 當核心線程達到最大, 且隊列滿以後新入隊的元素將開啓更多線程, 總數最大不超過這個值 long keepAliveTime, // 線程存活時間, 指核心線程外的線程 TimeUnit unit, //時間單位 BlockingQueue<Runnable> workQueue //線程隊列, 只有經過execute()方法調用的纔會進入 ) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
newSingleThreadExecutor()
corePoolSize=1 , maximumPoolSize=1 , keepAliveTime=0 , workQueue使用LinkedBlockingQueue
newCachedThreadPool()
corePoolSize=0 , maximumPoolSize=Integer.MAX_VALUE , keepAliveTime=60 , TimeUnit=SECONDS , workQueue使用 SynchronousQueue ; 同步隊列, 來即處理
newFixedThreadPool()
corePoolSize=maximumPoolSize=傳入的參數 , keepAliveTime=0 , workQueue使用 LinkedBlockingQueue ;
newWorkStealingPool()
使用ForkJoinPool
實例, 並行隊列,since 1.8
答: RUNNING(正在運行), STOP(不接受新任務, 再也不處理隊列中的任務, 中斷正在執行的線程), SHUTDOWN(不接受新任務, 但繼續隊列中的任務),TIDYING(全部任務均銷燬了, workcount=0, 線程池轉爲此狀態時會啓動鉤子方法terminated),TERMINATED(teminated()執行結束)
RUNNING -> SHUTDOWN :
shutdown()
, 或者隱式在finalize()
(RUNNING or SHUTDOWN) -> STOP :shutdownNow()
SHUTDOWN -> TIDYING : 隊列和池均爲空
STOP -> TIDYING : 池爲空
TIDYING -> TERMINATED :terminated()
執行完
答: execute()方法用來執行
Runnable
接口類型的任務, submit()能夠接受Runnable
也能夠接受Callable
.
答: 使用鎖
Lock
, 以及線程安全的類java.util.concurrent
, 代碼同步關鍵字synchronized
等
答: synchronized是重量級鎖, 若是資源被佔用則當前線程進入阻塞隊列, 清空緩存, 但不少時候剛剛掛起資源就釋放了, 也就是說資源徵用其實沒有想象的那麼頻繁, 通常資源總會被同一個線程佔用. 從1.6開始對其優化, 分爲三種級別, 偏向鎖,輕量級鎖,重量級鎖. 參考Java併發——Synchronized關鍵字和鎖升級,詳細分析偏向鎖和輕量級鎖的升級
偏向鎖, 在對象頭設置標識位和threadid, 偏向鎖不會主動釋放鎖, 若是同一線程再次獲取, 則比較threadid, 相同則無需cas加鎖解鎖, 若是不一致則查看對象頭中保存的線程是否存活, 不存活則當前線程設置爲偏向鎖, 存活則代表有多於一個線程競爭鎖, 此時鎖可能升級爲輕量級鎖.
輕量級鎖: 對於多個線程爭用鎖, 但線程持有鎖時間不長的情景. 使用自旋必定次數來等待鎖釋放. 從而減小阻塞.
重量級鎖: 對於自旋必定時間的線程, 超出限制後鎖可能膨脹爲重量級鎖, 由操做系統調度管理. 重量級鎖會阻塞線程, 防止CPU空轉.
鎖升級後再也不降級, 但偏向鎖能夠被重置爲無鎖狀態.
答: 多個線程間互相等待對方釋放本身所需資源(鎖)的狀況, 循環等待致使線程阻塞.
答: (1). 順序執行; (2).檢測死鎖; (3). 減少鎖粒度; (4).設置鎖超時時間
答: 線程本地變量, 爲每一個線程提供獨立的變量副本, 本線程修改的值不會影響到其餘線程的同名變量.
如數據庫連接, session
答: synchronized能夠修飾代碼塊, 方法, 靜態方法. 這三種狀況實現不一樣. 對於代碼塊, 在塊的開始和結束的地方虛擬機分別會插入monitorenter和monitorexit指令, 必須成對出現, monitor是實現鎖的機制, 一個線程持有monitor, 其餘線程就被掛起了. 對於方法, 虛擬機會在方法表中爲其設置access_flag狀態.
答: synchronized用於方法和代碼塊, volatile用於變量. valatile解決了變量在多線程環境下的可見性.synchronized解決了對臨界資源的訪問控制. volatile並不能保證原子性,synchronized能保證原子性; volatile不阻塞線程,synchronized會致使線程阻塞.volatile會防止指令重排.volatile效率更高.
答: synchronized是關鍵字, 封裝了java對鎖的實現. Lock是jdk提供的, 包含一系列預約義的類. synchronized內部實現加鎖解鎖, 異常時釋放鎖, Lock須要代碼中調用相關方法, 不解鎖就不會釋放. Lock抽象可讓程序員對鎖有更精細控制以及定製操做.
答: 參看54, 另外,ReentrantLock能夠設置超時, 可被中斷.
答: 其內部實現不是簡單的使用synchronized,而是一個更爲高效的方式CAS (compare and swap) + volatile和native方法,從而避免了synchronized的高開銷,執行效率大爲提高. 核心是
UnSafe
類, 直接經過操做系統API操做. atomic並不是無阻塞, 而是阻塞不在程序,線程級別, 而是在底層上面.
答: 反射是在程序運行時可以動態獲取和操做對象的能力.
答: 序列化就是將對象轉化爲可以進行網絡傳輸或存儲的數據格式. java的序列化須要對象實現serializable接口.
保存對象文件; 網絡傳輸; 遠程方法調用.
答: 動態代理是在運行時生成代理類. 好比原生的基於接口的代理或CGLib實現Spring 的AOP機制.
答: 基於java原生的接口方式的代理; 使用CGLib庫實現的基於類繼承的代理.
答: 克隆是Java對原型模式的實現, 克隆省去了new的開銷, 同時能夠保存對象的狀態.
答: (1).實現Cloneable接口並重寫clone()方法; (2).使用序列化反序列化實現克隆
答: 這就得區分java對象在內存中的存儲方式, 淺拷貝對於值類型,直接複製內容, 但對於引用類型, 只是複製了一份對真實對象的引用. 深拷貝就是須要將引用類型的變量內容也同時複製, 從而生成一個徹底不一樣的對象.
答: jsp:java server page. 與asp,asp.net等同樣,是java生態的服務端動態頁面技術. servlet : server端小程序, 重在控制.事實上jsp就是在servlet基礎上實現的, 但更着重前端頁面.
答: request: 封裝客戶端請求, 能夠接收參數; respose: 封裝服務端響應; pageContext: 頁面上下文; session: 會話信息; application: 應用級別的對象; out: 服務端輸出流對象; config: 配置對象; page: JSP頁面; exception: 封裝頁面拋出的異常.
答: (1).page : 本頁面相關的對象; (2). session: 表明一次會話做用域內的; (3).application: 應用程序級別的, 做用域最廣, 全局, (4).request : 一次請求內
答: session是服務端對象, cookie是存儲在客戶端瀏覽器特定目錄的; session理論上沒有容量限制,cookie不能太大, 也有個數限制; session更爲安全, cookie有僞造的風險;session通常存儲在內存, 或內存數據庫中, 也能夠存在關係數據庫;
答: 用戶初次登錄網站後, 服務端會給客戶端響應添加session id, 以後客戶端每次請求均帶有這個id, 服務端獲取後經過此id找到對應的session對象.
答: 能夠, session id 可能以請求參數或header之類的方式請求到客戶端.
答: (不瞭解struts) 下面是搜索到的答案.
(1). 攔截級別, struts是類級別的攔截, spring是方法級別攔截;(2). 數據獨立性: Spring mvc 方法之間基本獨立, 獨享request,response數據, 請求經過參數獲取, 返回ModelMap,方法之間不共享變量;struts2方法之間也獨立, 但全部action變量是共享的, 編碼和閱讀代碼不友好.(3). 攔截機制, spring mvc 用的獨立的aop方式;struts2有本身框架的攔截機制;(4)對ajax的支持: spring mvc 更方便, 使用@ResponseBody註解可實現; struts2須要插件或自定義;
答: PreparedStatement, 關鍵字或符號轉義, 過濾特殊字符
答: XSS: 跨站腳本攻擊, 是攻擊者在web頁面植入js代碼, 等頁面被瀏覽後代碼執行從而達到攻擊目的. 避免方法是對用戶輸入的內容進行編碼, 過濾js等關鍵字.
答: 跨站請求僞造, 是攻擊者盜用別人身份併發送惡意請求進行欺騙的手段. 避免方法是: 驗證請求來源, 只接受同源的請求; 添加驗證碼; 使用token驗證.
答: throw 是拋出異常的關鍵字, 後面是一個異常實例;throws是表示方法可能會拋出的異常, 後面是異常的類名, 用來方法前面上面.
答: final修飾變量, 方法, 類. 被修飾的代表不能被修改,重寫或繼承;finally是異常處理塊, 其中的代碼必然執行;finalize是類的析構方法, 通常不需本身定義.
答: try與其餘兩者之一必須成對存在.
答: 會執行, finally中的代碼無論什麼狀況下, 必然會執行.
答: NullPointerException, ClassNotFoundException,IOExcption,IndexOutOfBoundsException,ClassCastException,NoSuchMethodException...
答: 3XX 是跳轉響應碼. 301時永久跳轉, 對SEO友好, 302時臨時跳轉,可能會被攔截.
答: forward會帶有原頁面請求, redirect至關於從新打開一個頁面; redirect的地址欄會變, forward則不會; forward效率要高點.
答: 都是傳輸層協議.
tcp面向連接, udp非連接便可發送數據; tcp提供可靠的數據傳輸,udp沒法保證; tcp面向字節流, udp面向報文; tcp傳輸效率低, udp傳輸快;
答: 兩次握手的話, 服務端發出確認信號, 但客戶端未必會響應, 而此時鏈接以及創建, 但客戶端並非真的須要服務端, 這就形成了資源浪費.
答: 發送端: 發送端須要等緩衝區滿才發送, 形成粘包; 接受端: 接受端不及時接受緩衝區的包, 形成多個包接受.
答: 物理層, 數據鏈路層,網絡層, 傳輸層,會話層,表現層,應用層.
答: post比get更安全; get有限制, post沒限制; get地址欄顯式, 可收藏;post不行.get 可緩存;
答: 反向代理如njinx; 服務端設置CORS爲*; 單個接口設置@CrossOrigin; 使用jsonp;
答: Json with Padding, 利用scrpt的src能夠訪問不一樣源的特性, 加載遠程返回的js函數來執行.
答: 單例模式: 類本身管理自身的實例化, 節省資源; 工廠模式, 觀察者模式;代理模式, 模版方法, 策略模式, 生成器模式.
答: 抽象工廠用來生成一系列產品族, 工廠方法指示生成一種產品, 他們都支持增長產品. 簡單工廠更像是一種編程習慣, 用來管理產品的生成.
答: Spring流行,生態完善, 特別是spring boot, spring cload簡化了開發和部署; spring 是各類框架的粘合劑; spring將設計儘可能延遲, 開發者能夠儘可能晚地作決定, 好比修改配置便可替換某個類; Spring 容器更容易管理依賴; aop技術能夠抽離切面; spring提供事務支持.
答: 面向切面編程, 經過java原生或cglib加強來實現. aop能夠將一部分如事務, 日誌, 異常等統一的功能抽離, 統一維護.
答: ioc是控制反轉, 是將原來類自身管理它依賴的方式替換爲由容器統一管理, 這就將依賴作到很大程度解耦.
答: spring core 提供ioc; spring context ; dao, aop, web, mvc等.
答: setter注入, 構造函數注入. 另外還有編程注入, 但這方式太原始, 並不僅是spring的, 只能說它只是達成注入的一種方式.
答: 默認的bean是單例的, spring 並不能保證bean的線程安全.
spring的bean大可能是無狀態的, 因此大多狀況下不存在線程不安全的問題. 但若是須要保持有狀態的bean, 就必須使用其餘做業域了. 如prototype.
答: 六種: singleton, prototype, session, request,application, websocket. 後面四種僅僅在web環境下.
答: 四種方式, no 不使用, 經過ref等方式來完成; bytype 經過類型, byname 經過名字, constructor: 相似bytype只是應用於構造函數參數. bytype和byname能夠組裝數組.
答: 使用@Transaction的聲明式事務, 或編碼實現.
答: 事務隔離機制: 未提交讀,提交讀,可重複讀, 序列化; spring的事務隔離與數據庫相同, 但還有個默認方式, 即便用數據庫使用的隔離級別.
答: 請求-> DispatcherServlet-> handlermaping-> handler(controller action)-> modelAndView-> viewResolver->view
答: DispatcherServlet, HandlerMapping, ViewResolver, Controller, ModelAndView,LocaleResolver等.
答: 請求映射, 就是將http請求的特定url到特定的handler上.
答: 自動裝配, 使用該註解的字段,方法,構造函數自動完成依賴注入. 減小了配置.
答: Spring boot 是爲了簡化Spring開發的, 簡化了spring程序的初始搭建和開發部署, 提供了開箱即用的開發體驗和一套非功能性組件, 能夠作到幾乎沒有配置.
答: 配置簡單; 獨立運行,有內置的web容器; 自動配置,極少的xml配置文件; 快速搭建和部署;
答: bootstrap.XX 和 application.XX
答: properties 和 yml 兩種格式的配置文件, yml語法更嚴格, 能夠減小錯誤, 但缺少自由度, yml配置看起來有層次, 兩種方式各有優劣. yml不支持@PropertySource. 能夠經過實現
PropertySourceFactory
接口來實現.
答: 開發時使用devtools, 配置中添加spring.devtools.restart.enabled=true; idea中配置自動編譯.
答: jpa時規範, java persistence api. hibernate是框架, 基於jpa實現.
答: 基於spring boot 實現的一系列框架的合集. 提供了分佈式系統中非功能性的基礎實現, 如配置註冊中心, 路由, 熔斷, 負載均衡, 監控等. 只須要極少配置便可使用.
答: 當分佈式架構中的服務單元發生故障時或其餘緣由如流量過載等緣由時, 斷路器會根據設置的閥值斷定正常服務或快速返回錯誤, 這樣能夠防止服務長時間的等待, 從而防止故障蔓延.
答: Eureka, Feign, Ribbon, Hystrix,Zuul.
12、Hibernate
答: hibernate是對jdbc的封裝, 簡化了訪問數據庫的重複代碼; hibernate提供ORM實現, 簡化了DAO層的編碼; 具備數據庫可移植性; 緩存提高了效率.
答: Object Relation Mapping, 是將關係數據庫的表或視圖等映射爲程序中的對象. 這樣能夠簡化開發.
答: hibernate.show_SQL=true
答: 原生SQL, HQL, 條件查詢Criteria.
答: 能夠, 但final的不能被繼承, 也就不能使用代理模式實現延遲關聯來提高性能了.
答: 對象和值, Integer能夠爲null.
答: 讀取解析配置文件, 建立SessionFacotry, 打開Session, 建立事務, 操做, 提交事務, 關閉Session, 關閉SessionFactory.
答: load()支持延遲加載, get()不支持; 沒有OID指定的對象, get()返回null, load返回代理對象.
答: 分爲一級緩存和二級緩存; 一級緩存是Session緩存, Session做用域有效. 二級緩存是application緩存, 全局有效, 並支持三方緩存.
答: 臨時狀態(不受Session管理), 持久化狀態(持久化到數據庫中的), 遊離狀態(Session關閉後的對象).
答: getCurrentSession() 綁定當前線程, openSession()不會; getCurrentSession()受事務管理, openSession()須要手動管理事務.
答: 是的, hibernate使用反射實例化實體. 沒有無參構造會報異常.
答: #{} 是預編譯處理, ${}是字符替換. 使用#{}時, Mybatis會將其替換爲?, 這樣能夠防止SQL注入, 保證程序安全.
答: 物理分頁和邏輯分頁. RowBounds使用邏輯分頁. 分頁插件PageHelper或自定義分頁使用物理分頁.
答: 也不是, jdbc有個Fetch Size的設置, 只有當須要更多數據時, 它纔會從數據庫查詢更多數據.
答: 邏輯分頁時在內存中進行, 一次查詢出不少數據, 在內存進行分頁, 這種方式佔用大量內存, 可能致使內存溢出; 物理分頁是直接查詢出所需數據, 在數據庫分頁, 這種分頁按需返回數據, 但數據庫壓力可能較大.
答: 支持. 能夠設置lazyLoadingEnable=true啓用.
延遲加載是在使用實例的時候, 好比調用對象a.getName(), 若是發現a爲null, 則加載a並返回. 延遲加載就是在使用時纔去觸發查詢的SQL.
答: 一級緩存是基於PerpetualCache的HashMap本地緩存, 生命週期與SQLSession相同, 可能會出現髒數據, 在session關閉或清空後緩存失效. 默認開啓. 二級緩存也是基於PerpetualCache的HashMap本地緩存, 不一樣的是做用域爲Mapper級別, 能夠在多個Session間共享, 能夠自定義緩存如使用EhCache. 使用二級緩存須要類實現Serializable接口.
查詢順序: 二級緩存 --> 一級緩存 --> 數據庫.
更新策略: 同一做用域下發生更新後, 默認該做用域下的select緩存均clear.
答: Mybatis更靈活, 能夠本身寫sql; 可移植性hibernate要好; 二級緩存hibernate能夠自行更換;
答: 有三種基本執行器: (1). SimpleExecutor: 每執行一次update或select就開啓一個statement對象, 用完當即關閉statement對象; (2). ReuseExecutor: 執行update,select, 以sql語句做爲key查找statement對象, 存在則使用, 不存在則建立, 用完存在Map以備後面再用. (3). BatchExecutor: 執行update, 將多個sql添加到批處理中, 等待統一執行, 它緩存了多個statement對象, 等待統一處理.
答: 攔截器實現, 攔截sql, 而後重寫爲對應的分頁sql.
答: (1). 插件要實現interceptor接口
public interface Interceptor{ // 攔截的適合要執行的邏輯 Object intercept(Invocation invocation) throws Throwable; // 用於封裝目標對象, 該方法返回對象自己或其代理, 可決定是否要進行攔截進而決定要返回什麼樣的對象. Object plugin(Object target); // 在MyBatis進行配置插件的適合能夠配置自定義相關屬性, 接口實現對象的參數配置. void setProperties(Properties properties); }
(2). 插件應用的目標對象: Executor, StatementHandler,ParameterHandler, ResultSetHandler.
(3). 實現示例:
@Intercepts({ @Signature(type=Executor.class, method="query",args={ MappedStatement.class,Object.class,RowBounds.class, ResultHandler.class }) }) public class TestInterceptor implements Interceptor{ public Object intercept(Invocation invocation) throws Throwable{ Object target = invocation.getTarget();// 被代理對象 Method method = invocation.getMethod(); // 代理方法 Object[] args = invocation.getArgs(); //方法參數 ///....... 方法執行前的代碼 Object result = invocation.proceed(); ///........方法執行後的代碼 return result; } public Object plugin(Object target){ return Plugin.wrap(target,this); } }
答: rabbitmq是目前比較流行的amqp消息隊列, 適合使用的場景有: 1. 系統削峯填谷; 2. 延遲隊列; 3. 系統解耦.
答: 問題問的是構成rabbitmq的系統角色, rabbitmq是生產者/消費者模式的結構. 所以分爲生產者: 消息的建立方, 負責發送消息到消息服務器; 消費者: 消息接收方, 用於處理數據; 中介代理: 即rabbitmq自己, 用來接受消息並按必定數據格式存儲, 併爲消費者提供消息.
答:
答: 相似數據庫的實例, 每一個vhost有本身的一套隊列,交換機和綁定以及本身的權限機制.
答: 客戶端經過tcp連接到RabbitMQ服務器, 一旦經過了認證, 客戶端和服務器之間就建立了一條amqp信道, 信道是建立在真實tcp上的虛擬連接, amqp命令是經過信道發出去的, 每一個信道都有一個惟一的id, 不論發佈仍是訂閱均經過此信道完成.
答: 提供了事務支持; 能夠將channel設置爲confirm模式.
答: 把消息持久化到磁盤, 保證重啓數據不丟失; 集羣中至少有個物理磁盤, 保證消息落入磁盤.
答: 隊列queue必須設置持久化durable爲true; 消息推送投遞模式必須設置持久化, deliveryMode=2; 消息已經到達持久化交換機; 消息已經到達持久化隊列.
答: 持久化須要將數據寫入磁盤, 跟其餘磁盤io的系統同樣,這樣會下降服務器吞吐量, 下降性能.
答: direct, 默認方式, 發送消息給訂閱方, 對於多個訂閱方採用輪詢的方式進行; headers, 性能較差, 此類型幾乎用不到; fanout, 分發模式, 分發給全部訂閱者; topic: 匹配訂閱, 可使用正則匹配到消息隊列, 能匹配到的都能接收到.
答: 有兩種方式: 一是消息過時後進入死信交換機, 再由交換機轉發到延遲消費隊列, 實現延遲功能; 二是使用delayed-message-exchange插件實現延遲功能.
答: 高可用, 高容量
答: 磁盤節點, 可持久化數據; 內存節點, 高效.
答: 各節點之間用"-link"鏈接; 各節點使用erlang coolie值必須相同, 至關於密鑰, 用於認證; 整個集羣中必須包含一個磁盤節點.
答: 不是, 緣由有二: 存儲空間和性能.
答: 集羣能夠保持運行, 只是不能修改任何東西了. (1)不能建立隊列;(2)不能建立交換器;(3)不能建立綁定;(4)不能添加用戶;(5)不能更改權限;(6)不能添加刪除節點.
答: 須要先關閉內存節點, 再關閉磁盤節點, 不然可能會致使數據丟失.
答: 不能夠, kafka使用zookeeper協調管理kafka的節點服務器.
答: 兩種: 按過時時間保留, 按存儲消息大小保留.
答: 兩個規則爲或的關係, 只要一個知足要求即清除數據.
答: 傻逼問題, 傻逼答案... cpu, io, 網絡
答: 集羣節點最好不要超過7個, 節點越多消息複製須要的時間越長, 整個羣組的吞吐量就越低. 集羣數爲2N+1個較好. 超過一半故障集羣就不能用了, 單數容錯更高一點.
答: zookeeper是分佈式協調調度RPC框架, 它爲分佈式應用提供一致性服務, 包括配置註冊中心,域名服務,分佈式鎖等.
數據採用樹形方式, 能夠支持臨時和永久, 有序和無序兩種方式的任意組合.
答: 事件監聽, 文件存儲; 適用的場景包括: 發佈訂閱,配置註冊中心, 命名服務, leader選舉, 負載均衡, 分佈式隊列, 分佈式鎖等.
答: 單實例部署, 集羣部署.
答: Zookeeper 的核心是原子廣播,這個機制保證了各個Server之間的同步。實現這個機制的協議叫作Zab協議。Zab協議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。當服務啓動或者在領導者崩潰後,Zab就進入了恢復模式,當領導者被選舉出來,且大多數Server完成了和 leader的狀態同步之後,恢復模式就結束了。狀態同步保證了leader和Server具備相同的系統狀態。
爲了保證事務的順序一致性,zookeeper採用了遞增的事務id號(zxid)來標識事務。全部的提議(proposal)都在被提出的時候加上了zxid。實現中zxid是一個64位的數字,它高32位是epoch用來標識leader關係是否改變,每次一個leader被選出來,它都會有一個新的epoch,標識當前屬於那個leader的統治時期。低32位用於遞增計數。
答: 分佈式環境中, 有些業務邏輯只須要在集羣中的某臺服務器執行, 這樣能夠保證這些事務邏輯的原子性, 同時也保證只在一臺服務器執行,這樣能夠提升性能, 減小重複計算.等執行完成後結果被其餘的節點共享.
答: 可使用, 通常集羣的機器節點數爲2N+1, 只要有大於一半的服務器在線便可正常提供服務, 三臺宕機一臺依然有兩臺可用.
答: zookeeper採用註冊/監聽方式, 使用
Watcher
來實現對節點和路徑事件的監控.
十7、MySql
答: 1. 原子性, 每一個字段都只表示一個屬性; 2. 每一個字段均依賴於主鍵, 也就是一張表只表示一個對象; 3. 屬性不能傳遞依賴,也就是有傳遞依賴的地方要拆分爲不一樣表;
答: Innodb和myIASM兩種執行引擎的方式不一樣, Innodb會在內存中存儲表中的自增id, myiasm是在表中保留, 所以innodb重啓後會丟失最大id, 而會從現有表中計算因此結果爲6, myiasm爲8.
答: select version()
答: ACID是數據庫事務的特性, A是atomicity, 即原子性, 原子性保證一個事務以一個總體邏輯執行, 要麼成功, 要麼失敗, 執行完成後不會發生中間狀態; C是consistency, 即一致性, 即事務執行開始和結束後, 數據的完整性沒有遭到破壞; I是Isolation, 隔離性, 多個併發的事務對數據來講不會由於交叉執行而致使數據不一致, 數據庫存在四個隔離級別, 分別解決不一樣程度的數據隔離;D 是 durability, 是持久性, 事務執行後對數據修改時永久的, 數據保持完成.
答: char是固定長度的, varchar是可變長度的,char可能會存在空間浪費的狀況, varchar使用的空間是n+1, 其中有一個char單位用來保存長度, 性能方法, char的性能要高一點,
答: 大小不一樣, float是4字節的, double是8字節的.
答: 內鏈接是兩個表能匹配的數據, 左鏈接和右鏈接則分別以左表或右邊爲主, 展現出左表或右表的數據, 對於匹配不到的, 右表或左表展現爲null.
答: mysql或其餘數據庫的索引大多采用B+樹數據結構, B+樹自己就是有序結構, 能夠達到二分法的性能.
答: explain 查詢語句, 查看執行計劃
答: MySql.ini配置文件有默認的事務隔離配置, transaction-isolution=REPEATABLE-READ.
事務有四個級別的隔離方式, 分別爲:
髒讀: 一個事務能讀取另外一個事務未提交的數據; 不可重複讀: 一個事務內屢次讀取同一個數據;幻讀: 同一事務屢次讀取的數據不一致.
答: InnoDB: 提供了對數據庫的acid事務支持, 並提供行級鎖和外鍵約束, 它設計的目標就是處理大數據容量的數據庫系統. 它會在啓動時創建緩衝池, 用來緩存數據和索引. 但不支持全文索引, 啓動也比較慢. 不會保存行數, 但併發環境下的讀取效率很高.
MyIASM: 默認引擎, 不提供事務支持, 不支持行鎖和外鍵. 因此變動時會鎖表,效率比較低. 但其保存了行數, 讀多餘寫的操做可使用此搜索引擎.
答: 行鎖是在數據變動時僅會在當前行加鎖, 其餘行仍是能夠訪問的, 鎖的級別較小, 不容易發生阻塞.表鎖是變動時會對整個表加鎖, 性能低下, 不利於併發.
答: 樂觀鎖是默認沒有別的進程修改數據, 僅在提交更新時斷定數據版本號是否與修改前一致; 悲觀鎖是默認認爲數據在同一時間可能被其餘進程修改, 所以先鎖定數據, 修改後釋放鎖.
答: show processlist, explain, 查看日誌
答: 索引, 合適的查詢語句, 表分區, 正確的搜索引擎
答: redis是一種nosql數據庫, 是用C實現的, 具備高性能, 單線程, 支持持久化, 支持集羣的高可用內存數據庫.
用來作數據庫, 緩存, 消息中間件
答: 複製, 集羣, 持久化, 事務, 分佈式鎖,LUA腳本, LRU
答: (1) 持久化的支持, 數據可靠性: redis能夠作持久化, memcache是內存沒法持久化; (2) 底層實現方面: redis利用單線程, memcache多線程, 可使用多核CPU; (3). 數據結構方面: redis支持較多的數據結構, memcache僅僅是k-v結構;(4). 數據大小, 小於100kredis比較快, 大於100k,memcache較快, 但redis支持最大512M的數據, memcache最大爲1M; (5)應用場景: memcache適合讀多寫少, 或數據比較大的對象,redis適合讀寫都不少, 比較複雜的數據結構.
答: redis是基於內存操做的, CPU不會存在瓶頸, 既然CPU不是瓶頸, 單線程又很容易實現, 那麼redis天然就選擇用單線程了.
對於多個CPU的服務器, 能夠開多個redis實例來提升服務器資源使用率. 注意: redis4.0 開始可能會有條件地在某些操做時使用多線程.
183.什麼是緩存穿透?怎麼解決?
答: String, Set, ZSet, List, Hash
不常見的有: Bitmaps,Hyperloglogs 和地理空間(Geospatial)索引半徑查詢
答: Jedis, Redisson等, 官方推薦Redisson
答: jedis是對原生redis的簡單封裝, redisson是官方推薦的客戶端程序, 除了基本的命令, 還有更豐富的數據結構以及鎖的實現.
答: 更新時先刪除緩存, 設置數據過時時間, 異步更新數據.
答: aof, rdb
aof是寫日誌方式, 是按指定策略經過日誌恢復數據的方式.
rdb是快照方式, 支持同步(save)和異步方式(bgsave)保存數據. save會阻塞服務, 直到保存完成. bgsave不阻塞, 但可能運行期間的數據會發生丟失.
答: setNX命令, 返回1表示成功, 0位失敗.
答: 執行時間超過鎖超時時間時會致使併發問題.
答: 儘可能使用Redis的散列表, 把相關信息放在散列表裏面, 而不是各個字段單獨存儲, 這樣能夠有效減小內存.
答: 六種, 分別是volatile-ttl, 過時的數據集中清除超時的;volatile-lru,過時的裏面清除不經常使用的數據;volatile-random,過時的數據裏面隨機清除; allkeys-random, allkeys-lru, 與上面同樣, 只是範圍爲全部的數據集.no-enviction,禁止淘汰
答: redis是在進行持久化的時候會致使性能問題. 寫內存快照會阻塞主線程, 當快照較大時會較長時間的致使服務暫停, 全部主服務器最好不要寫快照. 主從複製的性能問題, 複製的速度和穩定性. 主從最好在一個局域網內.
答:
總的來講就是類加載器會將java代碼轉化爲字節碼, 運行時區把字節碼加載到內存, 爲了調用操做系統功能, 執行引擎須要調用本地方法.
答:
程序計數器, 堆, 棧, 方法區
棧又分爲虛擬機棧和本地方法棧.
方法區和堆是全部線程共享的, 其餘爲線程隔離.
程序計數器是記錄程序執行順序的一小塊內存區域, 存儲程序執行指令的行號信息, 存儲虛擬機字節碼指令地址, 本地方法時計數值爲空, 內存模型中不會發生 OutOfMemoryException
.
虛擬機棧是方法執行時同時建立的, 用於支持方法執行和調用的數據結構,棧幀用於存儲局部變量表、操做數棧、動態連接、方法返回地址和一些額外的附加信息.編譯程序代碼時,棧幀中須要多大的局部變量表、多深的操做數棧都已經徹底肯定了,而且寫入了方法表的 Code 屬性之中.
1. 局部變量表: 一組變量值存儲空間,用於存放方法參數和方法內部定義的局部變量, 局部變量表的容量以變量槽(Slot)爲最小單位. 局部變量表所需的內存空間在編譯期間完成分配; 2. 操做數棧: 最大深度也是在編譯的時候就肯定了.32 位數據類型所佔的棧容量爲 1,64 位數據類型所佔的棧容量爲 2。當一個方法開始執行時,它的操做棧是空的,在方法的執行過程當中,會有各類字節碼指令(好比:加操做、賦值元算等)向操做棧中寫入和提取內容,也就是入棧和出棧操做。 3. 動態鏈接: 每一個棧幀都包含一個指向運行時常量池(在方法區中,後面介紹)中該棧幀所屬方法的引用,持有這個引用是爲了支持方法調用過程當中的動態鏈接。Class 文件的常量池中存在有大量的符號引用,字節碼中的方法調用指令就以常量池中指向方法的符號引用爲參數。這些符號引用,一部分會在類加載階段或第一次使用的時候轉化爲直接引用(如 final、static 域等),稱爲靜態解析,另外一部分將在每一次的運行期間轉化爲直接引用,這部分稱爲動態鏈接。 4. 方法返回地址: 方法返回時可能須要在棧幀中保存一些信息,用來幫助恢復它的上層方法的執行狀態。通常來講,方法正常退出時,調用者的 PC 計數器的值就能夠做爲返回地址,棧幀中極可能保存了這個計數器值,而方法異常退出時,返回地址是要經過異常處理器來肯定的,棧幀中通常不會保存這部分信息
本地方法棧爲使用到的本地操做系統(Native)方法服務。
它用於存儲已經被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。運行時常量池是方法區的一部分.
堆是存儲對象信息的內存區域, 是 GC 主要工做區域, 虛擬機將堆又分爲 Eden, Survive, Old, Perm 等區塊, 通常新生代分配爲 1/4 到 1/3, 默認 3/8. 新生代的 Eden ,Survive 默認比例爲 8:1:1 .
直接內存:直接從操做系統中分配,所以不受 Java 堆大小的限制,可是會受到本機總內存的大小及處理器尋址空間的限制. NIO 機制能夠直接從操做系統中分配直接內存,即在堆外分配內存.
答:
堆是JVM分配的一塊共享內存區域, 佔用了虛擬機內存的絕大多數空間, 堆存儲的是對象的實例或數組, 這裏也是GC的主要區域. 棧是各線程獨立的內存區域, 在編譯時就已經肯定大小, 棧存儲方法執行時的相關信息, 包含局部變量表,操做數棧, 動態鏈接, 方法返回等信息.
答:
Queue
和 Stack
都是數據結構, Queue
支持 FIFO, Stack
支持 FILO. Queue
是接口, 繼承了 Collection
. Stack
則實現了 Vector
, 方法是線程安全的.
答:
Java 的類加載機制支持四種類加載器, customer -> app -> ext -> bootstrap bootstrap 是最頂級加載器, 用於加載 rt.jar , ext 次之, 加載javahome/lib下的其餘類. 雙親委派模型就是在類加載時當前加載器首先委託給上層加載器進行加載, 上層加載器沒法加載纔是本加載器進行加載, 這樣設計是基於安全性考慮, 這樣能夠避免本加載器加載覆蓋上層加載器的一些類, 好比 String
基於此模式必然會優先經過 bootstrap 加載.
答:
加載 -> 鏈接(驗證 -> 準備 -> 解析) -> 初始化
鏈接: 分爲三步
初始化: 靜態變量賦值, 靜態代碼塊執行
答:
經過垃圾對象標記算法, 分爲兩種:
JVM會起一個線程從全部的GC Roots開始往下遍歷,當遍歷完以後若是發現有一些對象不可到達,那麼就認爲這些對象已經沒有用了,須要被回收。四種引用類型: 強引用、軟引用、弱引用和虛引用.
答:
強引用、軟引用、弱引用和虛引用. 引用強度依次下降. 強引用不會被GC, 軟引用在內存不夠的狀況下會被回收; 弱引用只要開始GC, 就會被回收. 虛引用最弱, 必須和 ReferenceQueue 隊列一塊兒使用.
答:
複製算法: 新生代使用的算法, 分爲Eden,和兩個 Survive 區域, GC時將Survive 1的對象所有複製到2, 同時Eden中非垃圾對象也複製到2.
標記-整理: Old區域的回收, 首先標記出垃圾對象, 而後將對象整理存放在內存的一端, 這樣內存不會有碎片
標記-清除: 跟標記-整理相似, 不過GC時只清除垃圾對象. 可能致使內存不連續.
分代收集: 根據對象生命週期, 上述算法混合使用
答:
Serial, Serial Old, ParNew , Parallel Scavenge, Serial Old, Parallel Old, CMS, G1
具體參看面試題 關於垃圾收集的部分.
答:
CMS 追求最低停頓時間, 使用標記-清除算法. 通常與parnew 等收集器協同工做. 分四步: 1.初始標記, 2.併發標記, 3.重複標記, 4.併發清除. 1,3會致使停頓.
答:
新生代: Serial, ParNew, parallow scavenge (追求可控的吞吐量)
老生代: CMS (追求最低停頓時間) , Serial Old , parallow Old
G1 爲分代收集.
答:
新生代和老生代採用不一樣的收集算法, 新生代採用複製算法, 老生代採用標記-整理算法.
答:
jps, jinfo, jstat, jstack, jmap,jconsole,jvisualvm
參看這篇文章
答:
參看面試題 線上應用的 JVM 參數有哪些.