您好,登錄后才能下訂單哦!
這篇文章主要介紹了P6級Java面試題有哪些,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
一、String stringBuffer和stringBuilder
String:適用于少量字符串操作的情況,為字符串常量,即對象一旦創(chuàng)建之后對象是不可更改的。
StringBuffer:適用多線程下字符緩沖區(qū)進行大量操作的情況。屬于線程安全。
StringBuilder:適用于單線程下在字符緩沖區(qū)進行大量操作的情況。屬于線程不安全。
StringBuffer與StringBuilder均為字符串變量,對象是變量,即可以更改。StringBuilder所有方面都沒有被synchronized修飾,它的效率比StringBuffer要高。
二、HashMap的底層實現(xiàn)原理
HashMap底層是數組+鏈表實現(xiàn)的,它是一個entry類的數組,entry中包含key和value的值,允許key、value可以為null,通過key的hashcode計算在這個數組所在位置,遍歷這個鏈表從而查詢到值,hashMap默認的初始化容器大小為16,之后每次擴充為原來的2倍。屬于線程不安全的。
在JDK1.7及以前,HashMap中維護著Entry,Entry中維護著key,value以及hash和next指針,而整個HashMap實際就是一個Entry數組。
當向 HashMap 中 put 一對鍵值時,它會根據 key的 hashCode 值計算出一個位置,該位置就是此對象準備往數組中存放的位置。
如果該位置沒有對象存在,就將此對象直接放進數組當中;如果該位置已經有對象存在了,則順著此存在的對象的鏈開始尋找(為了判斷是否是否值相同,map不允許鍵值對重復),如果此鏈上有對象的話,再去使用 equals方法進行比較,如果對此鏈上的每個對象的 equals 方法比較為 false,則將該對象放到數組當中,然后將數組中該位置以前存在的那個對象鏈接到此對象的后面。
get方法類似,通過key取hash找到數組的某個位置,然后遍歷這個數組上的每個Entry,直到key值equals則返回。
如果Hash碰撞嚴重,那么JDK1.7中的實現(xiàn)性能就很差,因為每次插入都要遍歷完整條鏈去查看key值是否重復,每次get也要遍歷整個鏈,在JDK1.8中,由于鏈表的查找復雜度為O(n),而紅黑樹的查找復雜度為O(logn),JDK1.8中采用鏈表/紅黑樹的方式實現(xiàn)HashMap,達到某個閥值時,鏈表轉成了紅黑樹。
三、HashMap和Concurrent HashMap區(qū)別, Concurrent HashMap 線程安全嗎, ConcurrentHashMap如何保證線程安全?
HashMap不是線程安全的,ConcurrentHashMap是線程安全的,HashMap內部維護著一個Entry數組,而ConcurrentHashMap內部有一個Segment段,它將大的HashMap切分成若干個段(小的HashMap),然后讓數據在每一段上Hash,這樣多個線程在不同段上的Hash操作一定是線程安全的,所以只需要同步同一個段上的線程就可以了,這樣實現(xiàn)了鎖的分離,大大增加了并發(fā)量。ConcurrentHashMap的實現(xiàn)中還使用了不變模式final和volatile來保障線程安全
四、HashMap的put方法做了哪些操作
他會根據key的hashcode重新計算hash值,根據hash值得到這個元素在數據中的位置,如果數組在該位置上已經存放有其他元素了,那么在這個位置上的元素將以鏈表的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾。
五、HashMap的缺點
HashMap不支持并發(fā)操作,所以不適用于多線程環(huán)境,在高并發(fā)狀態(tài)下,如果產生同時put操作,并且在put時剛好遇上要擴容,可能會形成鏈環(huán),如果get的key的hashcode值剛好在鏈環(huán)的位置,而這個key對應的值為null或不存在就會進入死循環(huán),耗盡cpu內存。
六、ConcurrentHashMap
底層是數組+紅黑樹+鏈表實現(xiàn),可以替代HashTable,因為使用了多個鎖代替hashTable中的單個鎖,也就是鎖分離技術,hashTable是鎖住了整個數組導致效率特別低,屬于線程安全。
七、Springmvc的工作原理
用戶發(fā)送請求至前端控制器DispatcherServlet,DispatcherServlet收到請求調用handlerMapping處理器映射器,解析請求對應的handler,開始由handlerAdapter適配器處理請求,并處理相應的業(yè)務邏輯并返回一個ModelAndView對象,根據返回的modelAndView選擇一個合適視圖解析器返回給DispatcherServlet,視圖解析器根據view和model渲染頁面。
八、集合的父類及各子類的區(qū)別
Collection
├List 允許重復值、有序容器,保持了每個元素的插入順序
│├LinkedList 線程不安全增刪改速度快,基于鏈表數據結構
│├ArrayList 線程不安全查詢速度快,基于動態(tài)數組結構
│└Vector 線程安全
│└Stack
├set 不允許重復值、無序容器,無法保證元素的存儲順序,可以通過TreeSet的comparator或者comparable維護一個排序順序
│├HashSet 線程不安全無序(存入與取出時順序不同)不重復,無索引,底層hash表結構查詢刪除快,增改慢。
│├TreeSet 是sortedSet接口的唯一實現(xiàn),可以進行排序
九、什么是線程安全與不安全
線程安全是多個線程訪問時,采用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問,直到該線程讀取完,其他線程才可使用,不會出現(xiàn)數據不一致或者數據污染。
線程不安全就是不提供數據訪問保護,有可能出現(xiàn)多個線程后更改數據造成所得到數據時臟數據。
十、為什么使用reids,用redis都做了些什么
Redis是一個開源的key-value型數據庫,運行在內存,速度快,同時支持持久化,支持的數據結構豐富(String,list,set,sorted set,hash),支持訂閱發(fā)布功能。
String:(常用命令get,set,incr,decr,mget)常規(guī)的key-value緩存應用。統(tǒng)計訪問次數,關注人數。
Hash(常用命令hget,hset,hgetall)省市區(qū)聯(lián)動,用戶信息
List(常用命令 Ipush,rpush,Ipop)用戶關注列表
Set 注冊用戶用戶名不能重復,使用set記錄注冊用戶
十一、Jvm如何調優(yōu)
VisualVM:jdk自帶,功能強大
堆信息查看:觀察內存釋放情況、集合類檢查、對象樹-----(查看堆空間的大小分配【年輕代、年老代、持久代分配】、提供即時的垃圾回收功能、垃圾監(jiān)控),可以解決年老代年輕代大小劃分是否合理、內存泄漏、垃圾回收算法設置是否合理。
線程監(jiān)控:可以查看線程在系統(tǒng)中的數量,各個線程都處在什么狀態(tài)下、死鎖檢查
熱點分析:cpu熱點---檢查系統(tǒng)哪些方面占用大量cpu時間,內存熱點-------檢查哪些對象在系統(tǒng)中的數量最大。
內存泄漏檢查:在錯誤的使用下導致使用完畢的資源無法回收,引起系統(tǒng)錯誤。常表現(xiàn)年老代空間被占滿(java heap space)一般根據垃圾回收前后情況對比,同時根據對象引用情況分析,基本可以找到泄漏點。
持久代被沾滿:無法為新的class分配存儲空間而引發(fā)的異常,在java大量的反射的使用會造成,大量動態(tài)反射生成的類不斷被加載。解決:-XX:MaxPermSize=16m
堆棧溢出:一般是遞歸沒返回,或者循環(huán)調用造成
線程池棧滿:java中一個線程空間大小是有限的,在jdk5以后這個值是1m。解決:增加線程棧大小,-Xss2m
十二、GC垃圾回收機制
什么時候:eden滿了minor gc,升到老年代的對象大于老年代剩余空間full gc,或者小于時被HandlePromotionFailure參數強制full gc
對什么東西:從root搜索不到,而且經過第一次標記,清理后仍然沒有復活的對象。
做什么事情:刪除不使用的對象,騰出內存空間。
算法:
1、標記-清除:分為標記和清除兩個階段,首先標記出所有需要回收的對象,標記完成后統(tǒng)一回收所有被標記的對象。
2、復制算法:它將可用的內存分為兩塊,每次只用其中一塊,當這一塊內存用完了,就將還存活的對象復制到另一塊上,然后再把已經使用過的內存空間一次性清理掉。
3、標記-整理算法:是讓所有存活的對象都向一端移動,然后直接清理掉邊界以外的內存。
十三、 JVM如何GC,新生代,老年代,持久代,都存儲哪些東西?
JVM通過可達性(可觸及性)分析算法標記出哪些對象是垃圾對象,然后將垃圾對象進行回收,在新生代中采用復制算法,在老年代中采用標記清理或標記壓縮算法。
新生代存儲了新new出的對象,老年代存儲了大的對象和多次GC后仍然存在的老年對象,持久代存儲了類信息,常量(JDK7中String常量池被移到堆中),靜態(tài)變量(JDK7中被移到了Java堆),類方法
十四、 強引用、軟引用、弱引用、虛引用的區(qū)別
強引用:是最難被GC回收的,寧可虛擬機拋出異常,中斷程序,也不會去回收該對象。(Object o=new Object())
軟引用:非必須引用,內存溢出之前進行回收。軟引用主要用戶實現(xiàn)類似緩存的功能,在內存足夠的情況下直接通過軟引用取值,無需從繁忙的真實來源查詢數據,提升速度;當內存不足時,自動刪除這部分緩存數據,從真正的來源查詢這些數據。
弱引用:第二次垃圾回收時回收。弱引用主要用于監(jiān)控對象是否已經被垃圾回收器標記為即將回收的垃圾,可以通過弱引用的isEnQueued方法返回對象是否被垃圾回收器標記。
虛引用:垃圾回收時回收,無法通過引用取到對象值。虛引用主要用于檢測對象是否已經從內存中刪除。
十五、Spring的原理
內部核心是ioc,動態(tài)注入,讓一個對象的創(chuàng)建不用new了,可以自動生成,這其實就是利用了java里的反射,反射其實就是在運行時動態(tài)的去創(chuàng)建、調用對象,spring就是在運行時,跟xml spring的配置文件來動態(tài)的創(chuàng)建對象,和調用對象的方法。
Spring還有一個核心就是AOP面向切面編程,可以為某一類對象進行監(jiān)督和控制從而達到堆一個模塊擴充的功能。這些都是通過配置類達到的。
十六、Aop如何實現(xiàn)
靜態(tài)代理:由程序員創(chuàng)建或特定工具自動生成源代碼,再對其編譯。在程序運行時,代理類.class文件就已經存在了
動態(tài)代理:在程序運行時,運用發(fā)射機制動態(tài)創(chuàng)建而成。
Cglib動態(tài)代理:針對類實現(xiàn)的代理。它的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現(xiàn)增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。
JDK的動態(tài)代理依靠接口實現(xiàn),如果有些類沒有實現(xiàn)接口,則不能使用jdk代理,就要使用cglib代理了。
十七、MySQL如何優(yōu)化
使用查詢緩存優(yōu)化查詢。(例如NOW(),RAND()或其他SQL函數都不會開啟查詢緩存,因為返回是會不定的易變得,所以你需要的就是一個變量來替代mysql的函數,從而開啟緩存)
使用EXPLANIN關鍵字檢測查詢(可以使我們知道MYSQL是如何處理SQL語句的,幫助分析查詢語句或是表結構性能瓶頸;索引主鍵是如何被利用的,數據表是如何被搜索或排序的,語句格式:EXPLAIN+SELECT語句)
當只有一行數據時使用LIMIT 1(可以增加性能,會查到第一條數據后停止搜索)
為搜索字段建立索引(普通索引INDEX:適用于name、email等一般屬性,唯一索引UNIQUE:要求索引字段值在表中是唯一的,唯一索引允許有空值。適用于身份證號碼、用戶賬戶等,全文索引:適用于VARCHAR和TEXT類型字段)
在jion表的時候使用相當類型的列,并將其索引(存在很多jion查詢時,保證兩個表中jion的字段時被建立索引的,這樣mysql會啟動優(yōu)化JION的sql語句機制)
避免使用 *
永遠為每一張表設置一個ID主鍵
盡可能的不要賦值為NULL(會占用存儲空間,程序判斷更加復雜,索引不存儲null值,使用not null約束以及默認值。)
固定長度的表會更快(容易計算下一個數據的偏移量,容易被緩存和重建。)
垂直分割:是一種把數據庫中的表按列變成幾張表的方法,這樣可以降低表的復雜度和字段數目
拆分大的或(這兩個大操作會鎖表,這樣別的操作就進不來了,可以使用LIMIT控制操作記錄的數量)
感謝你能夠認真閱讀完這篇文章,希望小編分享的“P6級Java面試題有哪些”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業(yè)資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。