<cite id="tt1p7"></cite>
<var id="tt1p7"><strike id="tt1p7"><listing id="tt1p7"></listing></strike></var><menuitem id="tt1p7"><strike id="tt1p7"></strike></menuitem><cite id="tt1p7"><span id="tt1p7"><var id="tt1p7"></var></span></cite><cite id="tt1p7"></cite>
<var id="tt1p7"><strike id="tt1p7"></strike></var>
<var id="tt1p7"><video id="tt1p7"></video></var>
<var id="tt1p7"><strike id="tt1p7"></strike></var>
<var id="tt1p7"><strike id="tt1p7"></strike></var>
<var id="tt1p7"><strike id="tt1p7"></strike></var>
<var id="tt1p7"></var>
<var id="tt1p7"></var>

送你一份P6級Java面試題(一)

2019-11-15 16:10:59

法甲比分直播

原標題:送你一份P6級Java面試題(一)

,英文名jacksonKang,是一名努力成長中的Java愛好者

http://mayiyk.cn/article/6

和stringBuilder

String:適用于少量字符串操作的情況,為字符串常量,即對象一旦創建之后對象是不可更改的。

StringBuffer:適用多線程下字符緩沖區進行大量操作的情況。屬于線程安全。

StringBuilder:適用于單線程下在字符緩沖區進行大量操作的情況。屬于線程不安全。

StringBuffer與StringBuilder均為字符串變量,對象是變量,即可以更改。StringBuilder所有方面都沒有被synchronized修飾,它的效率比StringBuffer要高。

的底層實現原理

HashMap底層是數組+鏈表實現的,它是一個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中的實現性能就很差,因為每次插入都要遍歷完整條鏈去查看key值是否重復,每次get也要遍歷整個鏈,在JDK1.8中,由于鏈表的查找復雜度為O(n),而紅黑樹的查找復雜度為O(logn),JDK1.8中采用鏈表/紅黑樹的方式實現HashMap,達到某個閥值時,鏈表轉成了紅黑樹。

和ConcurrentHashMap區別,ConcurrentHashMap線程安全嗎,ConcurrentHashMap如何保證線程安全?

HashMap不是線程安全的,ConcurrentHashMap是線程安全的,HashMap內部維護著一個Entry數組,而ConcurrentHashMap內部有一個Segment段,它將大的HashMap切分成若干個段(小的HashMap),然后讓數據在每一段上Hash,這樣多個線程在不同段上的Hash操作一定是線程安全的,所以只需要同步同一個段上的線程就可以了,這樣實現了鎖的分離,大大增加了并發量。ConcurrentHashMap的實現中還使用了不變模式final和volatile來保障線程安全

的put方法做了哪些操作

他會根據key的hashcode重新計算hash值,根據hash值得到這個元素在數據中的位置,如果數組在該位置上已經存放有其他元素了,那么在這個位置上的元素將以鏈表的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾。

的缺點

HashMap不支持并發操作,所以不適用于多線程環境,在高并發狀態下,如果產生同時put操作,并且在put時剛好遇上要擴容,可能會形成鏈環,如果get的key的hashcode值剛好在鏈環的位置,而這個key對應的值為null或不存在就會進入死循環,耗盡cpu內存。

底層是數組+紅黑樹+鏈表實現,可以替代HashTable,因為使用了多個鎖代替hashTable中的單個鎖,也就是鎖分離技術,hashTable是鎖住了整個數組導致效率特別低,屬于線程安全。

的工作原理

用戶發送請求至前端控制器DispatcherServlet,DispatcherServlet收到請求調用handlerMapping處理器映射器,解析請求對應的handler,開始由handlerAdapter適配器處理請求,并處理相應的業務邏輯并返回一個ModelAndView對象,根據返回的modelAndView選擇一個合適視圖解析器返回給DispatcherServlet,視圖解析器根據view和model渲染頁面。Collection├List允許重復值、有序容器,保持了每個元素的插入順序│├LinkedList線程不安全增刪改速度快,基于鏈表數據結構│├ArrayList線程不安全查詢速度快,基于動態數組結構│└Vector線程安全│└Stack├set不允許重復值、無序容器,無法保證元素的存儲順序,可以通過TreeSet的comparator或者comparable維護一個排序順序│├HashSet線程不安全無序(存入與取出時順序不同)不重復,無索引,底層hash表結構查詢刪除快,增改慢。│├TreeSet是sortedSet接口的唯一實現,可以進行排序

線程安全是多個線程訪問時,采用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其他線程不能進行訪問,直到該線程讀取完,其他線程才可使用,不會出現數據不一致或者數據污染。

線程不安全就是不提供數據訪問保護,有可能出現多個線程后更改數據造成所得到數據時臟數據。

reids,用redis都做了些什么

Redis是一個開源的key-value型數據庫,運行在內存,速度快,同時支持持久化,支持的數據結構豐富(String,list,set,sortedset,hash),支持訂閱發布功能。String:(常用命令get,set,incr,decr,mget)常規的key-value緩存應用。統計訪問次數,關注人數。Hash(常用命令hget,hset,hgetall)省市區聯動,用戶信息List(常用命令Ipush,rpush,Ipop)用戶關注列表Set注冊用戶用戶名不能重復,使用set記錄注冊用戶

如何調優

VisualVM:jdk自帶,功能強大

堆信息查看:觀察內存釋放情況、集合類檢查、對象樹-----(查看堆空間的大小分配【年輕代、年老代、持久代分配】、提供即時的垃圾回收功能、垃圾監控),可以解決年老代年輕代大小劃分是否合理、內存泄漏、垃圾回收算法設置是否合理。

線程監控:可以查看線程在系統中的數量,各個線程都處在什么狀態下、死鎖檢查

熱點分析:cpu熱點---檢查系統哪些方面占用大量cpu時間,內存熱點-------檢查哪些對象在系統中的數量最大。

內存泄漏檢查:在錯誤的使用下導致使用完畢的資源無法回收,引起系統錯誤。常表現年老代空間被占滿(javaheapspace)一般根據垃圾回收前后情況對比,同時根據對象引用情況分析,基本可以找到泄漏點。

持久代被沾滿:無法為新的class分配存儲空間而引發的異常,在java大量的反射的使用會造成,大量動態反射生成的類不斷被加載。解決:-XX:MaxPermSize=16m

堆棧溢出:一般是遞歸沒返回,或者循環調用造成

線程池棧滿:java中一個線程空間大小是有限的,在jdk5以后這個值是1m。解決:增加線程棧大小,-Xss2m

GC垃圾回收機制

什么時候:eden滿了minorgc,升到老年代的對象大于老年代剩余空間fullgc,或者小于時被HandlePromotionFailure參數強制fullgc

對什么東西:從root搜索不到,而且經過第一次標記,清理后仍然沒有復活的對象。

做什么事情:刪除不使用的對象,騰出內存空間。

算法:

、標記-清除:分為標記和清除兩個階段,首先標記出所有需要回收的對象,標記完成后統一回收所有被標記的對象。

、復制算法:它將可用的內存分為兩塊,每次只用其中一塊,當這一塊內存用完了,就將還存活的對象復制到另一塊上,然后再把已經使用過的內存空間一次性清理掉。

、標記-整理算法:是讓所有存活的對象都向一端移動,然后直接清理掉邊界以外的內存。

JVM如何GC,新生代,老年代,持久代,都存儲哪些東西?

JVM通過可達性(可觸及性)分析算法標記出哪些對象是垃圾對象,然后將垃圾對象進行回收,在新生代中采用復制算法,在老年代中采用標記清理或標記壓縮算法。新生代存儲了新new出的對象,老年代存儲了大的對象和多次GC后仍然存在的老年對象,持久代存儲了類信息,常量(JDK7中String常量池被移到堆中),靜態變量(JDK7中被移到了Java堆),類方法

強引用、軟引用、弱引用、虛引用的區別

強引用:是最難被GC回收的,寧可虛擬機拋出異常,中斷程序,也不會去回收該對象。(Objecto=newObject)

軟引用:非必須引用,內存溢出之前進行回收。軟引用主要用戶實現類似緩存的功能,在內存足夠的情況下直接通過軟引用取值,無需從繁忙的真實來源查詢數據,提升速度;當內存不足時,自動刪除這部分緩存數據,從真正的來源查詢這些數據。

弱引用:第二次垃圾回收時回收。弱引用主要用于監控對象是否已經被垃圾回收器標記為即將回收的垃圾,可以通過弱引用的isEnQueued方法返回對象是否被垃圾回收器標記。

虛引用:垃圾回收時回收,無法通過引用取到對象值。虛引用主要用于檢測對象是否已經從內存中刪除。

的原理

內部核心是ioc,動態注入,讓一個對象的創建不用new了,可以自動生成,這其實就是利用了java里的反射,反射其實就是在運行時動態的去創建、調用對象,spring就是在運行時,跟xmlspring的配置文件來動態的創建對象,和調用對象的方法。

Spring還有一個核心就是AOP面向切面編程,可以為某一類對象進行監督和控制從而達到堆一個模塊擴充的功能。這些都是通過配置類達到的。

Aop如何實現

靜態代理:由程序員創建或特定工具自動生成源代碼,再對其編譯。在程序運行時,代理類.class文件就已經存在了。

動態代理:在程序運行時,運用發射機制動態創建而成。

Cglib動態代理:針對類實現的代理。它的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。

JDK的動態代理依靠接口實現,如果有些類沒有實現接口,則不能使用jdk代理,就要使用cglib代理了。

MySQL如何優化

使用查詢緩存優化查詢。(例如NOW,RAND或其他SQL函數都不會開啟查詢緩存,因為返回是會不定的易變得,所以你需要的就是一個變量來替代mysql的函數,從而開啟緩存)

使用EXPLANIN關鍵字檢測查詢(可以使我們知道MYSQL是如何處理SQL語句的,幫助分析查詢語句或是表結構性能瓶頸;索引主鍵是如何被利用的,數據表是如何被搜索或排序的,語句格式:EXPLAIN+SELECT語句)

當只有一行數據時使用LIMIT1(可以增加性能,會查到第一條數據后停止搜索)

為搜索字段建立索引(普通索引INDEX:適用于name、email等一般屬性,唯一索引UNIQUE:要求索引字段值在表中是唯一的,唯一索引允許有空值。適用于身份證號碼、用戶賬戶等,全文索引:適用于VARCHAR和TEXT類型字段)

在jion表的時候使用相當類型的列,并將其索引(存在很多jion查詢時,保證兩個表中jion的字段時被建立索引的,這樣mysql會啟動優化JION的sql語句機制)

避免使用select*

永遠為每一張表設置一個ID主鍵

盡可能的不要賦值為NULL(會占用存儲空間,程序判斷更加復雜,索引不存儲null值,使用notnull約束以及默認值。)

固定長度的表會更快(容易計算下一個數據的偏移量,容易被緩存和重建。)

垂直分割:是一種把數據庫中的表按列變成幾張表的方法,這樣可以降低表的復雜度和字段數目

拆分大的delete或insert(這兩個大操作會鎖表,這樣別的操作就進不來了,可以使用LIMIT控制操作記錄的數量)

關聯推薦:

END

責任編輯:

上一篇:

下一篇:

Copyright? 2015-2020 南譙信息社版權所有
一元微信红包群免押金