聊聊基礎01

摘要:最近和女朋友聊天,說個人工做須要做出調整,當前狀態下壓力太大,急需經過提供自身的專業技能來做出改變,因此便有了這個基礎知識的整理。原本這個帖子是發佈在簡書的,由於考慮到簡書比較好編輯和閱覽,可是當我發佈到簡書後,女朋友居然驚訝和確定我終於開始寫博客了,因而比較汗顏,就仍是迴歸發佈到這裏來吧。後續針對這些基礎知識作更深次,更全面的研究,本基礎的一些問題來源:http://blog.csdn.net/exceptional_derek/article/details/69525715html

一:基礎類

 1.hashmap的基本原理,內部數據結構,put操做的總體流程,是否線程安全以及爲何?jdk8對hashmap作了哪些優化?

    答:HashMap是基於哈希表的Map接口的非同步實現。此實現提供全部可選的映射操做,並容許使用null值和null鍵。此類不保證映射的順序,特別是它不保證該順序恆久不變,HashMap其實是一個「鏈表散列」的數據結構,即數組和鏈表的結合體。咱們往HashMap中put元素的時候,先根據key的hashCode從新計算hash值,根據hash值獲得這個元素在數組中的位置(即下標),若是數組該位置上已經存放有其餘元素了,那麼在這個位置上的元素將以鏈表的形式存放,新加入的放在鏈頭,最早加入的放在鏈尾。若是數組該位置上沒有元素,就直接將該元素放到此數組中的該位置上。對HashMap的操做不是線程安全的,經過觀察源碼發現,當多個線程在某一個時刻同時對HashMap作結構性的修改,咱們能夠看到整個方法實現中沒有任何的同步機制,那麼存在一個線程獲取或者修改數據結構時,存在另一個線程獲取了一個錯誤的結果。jdk8對hashMap的數據結構的改變有個調整,當數組達到必定的閾值時,bucket就會由鏈表轉換爲紅黑樹的方式進行存儲,而不是進行table的擴容。java

2.String類爲何是不可變的?StringBuilder和StringBuffer的區別,字符串常量池,StringBuffer爲何是線程安全?加號的底層原理?

答:首先String類是用final關鍵字修飾,這說明String不可繼承,String類的成員字段value是個char[]數組,並且是用final修飾的。final修飾的字段建立之後就不可改變。不可變的好處:1.1.參考java字符串池的設計模式。好比兩個字符串值相等的變量,他們只會生成一個對象放到常量池中,而後兩個變量都指向它,提高效率。1.2.安全性,若是String類能夠被修改,那麼在多線程的狀況下會形成安全漏洞。2.1 StringBuilder和StringBuffer的區別:他們都是建立字符串的經常使用類,長度都是能夠擴充的,實現了CharSequence接口。StringBuilder非線程安全,StringBuffer線程安全,因此一般在單線程環境下能夠考慮是用StringBuilder來提高速度和效率,而在多線程的環境下則應該使用SringBuffer來保證線程安全。node

3.反射、accessible,動態代理的原理,jdk動態代理與cglib的區別與各自的實現原理?

答:反射的機制是在編譯時並不肯定的哪一個類被jvm加載,在程序運行的時候才加載、探知、自審。動態代理類的字節碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。cglib是針對類來實現代理的,他的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現加強,但由於採用的是繼承,因此不能對final修飾的類進行代理。二者區別:jdk的代理是利用反射生成字節碼,並生成對象,前提是隻能代理實現了接口的類,cglib是直接修改目標類的字節碼生成對象,由於原理是繼承,因此不能對final修飾的類進行代理。http://rejoy.iteye.com/blog/1627405https://my.oschina.net/tearsky/blog/635321mysql

4.自動裝箱,賦值操做,在內存裏面是如何實現的?

答:自動裝箱是將內置類型轉換爲對應的包裝類型,在自動裝箱的過程當中,程序會建立一個包裝類型的對象,而後將該變量指向這個新建立的對象,完成裝箱操做。程序員

5.接口和抽象類的區別

答:redis

一、抽象類和接口都不能直接實例化,若是要實例化,抽象類變量必須指向實現全部抽象方法的子類對象,接口變量必須指向實現全部接口方法的類對象。算法

二、抽象類要被子類繼承,接口要被類實現。spring

三、接口只能作方法申明,抽象類中能夠作方法申明,也能夠作方法實現。sql

四、接口裏定義的變量只能是公共的靜態的常量,抽象類中的變量是普通變量。數據庫

五、抽象類裏的抽象方法必須所有被子類所實現,若是子類不能所有實現父類抽象方法,那麼該子類只能是抽象類。一樣,一個實現接口的時候,如不能所有實現接口方法,那麼該類也只能爲抽象類。

六、抽象方法只能申明,不能實現,接口是設計的結果 ,抽象類是重構的結果。

七、抽象類裏能夠沒有抽象方法。

八、若是一個類裏有抽象方法,那麼這個類只能是抽象類。

九、抽象方法要被實現,因此不能是靜態的,也不能是私有的。

十、接口可繼承接口,並可多繼承接口,但類只能單根繼承。

6.concurrenthashmap的原理,內部數據結構,如何提升併發性,存在全鎖嗎?jdk8中作了哪些優化。

答:ConcurrentHashMap容許多個修改操做併發進行,其關鍵在於使用了鎖分離技術。它使用了多個鎖來控制對hash表的不一樣部分進行的修改。ConcurrentHashMap內部使用段(Segment)來表示這些不一樣的部分,每一個段其實就是一個小的hash table,它們有本身的鎖。只要多個修改操做發生在不一樣的段上,它們就能夠併發進行。

改進一:取消segments字段,直接採用transient volatile HashEntry[] table保存數據,採用table數組元素做爲鎖,從而實現了對每一行數據進行加鎖,進一步減小併發衝突的機率。

改進二:將原先table數組+單向鏈表的數據結構,變動爲table數組+單向鏈表+紅黑樹的結構。對於hash表來講,最核心的能力在於將key hash以後能均勻的分佈在數組中。若是hash以後散列的很均勻,那麼table數組中的每一個隊列長度主要爲0或者1。但實際狀況並不是老是如此理想,雖然ConcurrentHashMap類默認的加載因子爲0.75,可是在數據量過大或者運氣不佳的狀況下,仍是會存在一些隊列長度過長的狀況,若是仍是採用單向列表方式,那麼查詢某個節點的時間複雜度爲O(n);所以,對於個數超過8(默認值)的列表,查看源碼應該是16,jdk1.8中採用了紅黑樹的結構,那麼查詢的時間複雜度能夠下降到O(logN),能夠改進性能。當獲取modelcount時,會全鎖來統計個數。

詳細講解:http://www.importnew.com/22007.html

http://nanguocoffee.iteye.com/blog/907824

7.hashset的原理?

答:HashSet中add方法調用的是底層HashMap中的put()方法,而若是是在HashMap中調用put,首先會判斷key是否存在,若是key存在則修改value值,若是key不存在這插入這個key-value。而在set中,由於value值沒有用,也就不存在修改value值的說法,所以往HashSet中添加元素,首先判斷元素(也就是key)是否存在,若是不存在這插入,若是存在着不插入,這樣HashSet中就不存在重複值。

8.GC原理,分代機制,可達性分析?

答:對傳統的、基本的GC實現來講,因爲它們在GC的整個工做過程當中都要「stop-the-world」,若是能想辦法縮短GC一次工做的時間長度就是件重要的事情。若是說收集整個GC堆耗時太長,那不如只收集其中的一部分?因而就有好幾種不一樣的劃分(partition)GC堆的方式來實現部分收集,而分代式GC就是這其中的一個思路。

9.JVM參數有哪幾種,如何調優?

-Xmx2g //JVM最大容許分配的堆內存,按需分配

-Xms2g //JVM初始分配的堆內存,通常和Xmx配置成同樣以免每次gc後JVM從新分配內存。-Xmn256m //年輕代內存大小,整個JVM內存=年輕代 + 年老代 + 持久代年輕代分三個區, 分別是enden區和兩個survivor區。

10.JMM特性有哪些?

1.可見性:JMM提供了volatile變量定義、final、synchronized塊來保證可見性。

2.有序性:這個概念是相對而言的,若是在本線程內,全部的操做都是有序的,若是在一個線程觀察另外一個線程,全部的操做都是無序的,前句是「線程內表現爲串行行爲」,後句是「指令的重排序」和「工做內存和主內存同步延遲」現象,模型提供了volatile和synchronized來保證線程之間操做的有序性。

3.重排序:在執行程序時爲了提升性能,編譯器和處理器經常會對指令作重排序(編譯器、處理器),就是由於這些重排序,因此可能會致使多線程程序出現內存可見性問題(數據安全問題)和有序性問題。可見性、原子性、有序性.

十一、什麼是跳錶?

 

12.static關鍵字的做用?

答:1.被static修飾的變量屬於類變量,能夠經過類名.變量名直接引用,而不須要new出一個類來。

2.被static修飾的方法屬於類方法,能夠經過類名.方法名直接引用,而不須要new出一個類來。

3.靜態塊也是static的重要應用之一。也是用於初始化一個類的時候作操做用的,和靜態變量、靜態方法同樣,靜態塊裏面的代碼只執行一次,且只在初始化類的時候執行。

這個用得相對比前面的用法少多了,static通常狀況下來講是不能夠修飾類的, 若是static要修飾一個類,說明這個類是一個靜態內部類(注意static只能修飾一個內部類),也就是匿名內部類。

4.import static是JDK1.5以後的新特性,這兩個關鍵字連用能夠指定導入某個類中的指定靜態資源,而且不須要使用類名.資源名,能夠直接使用資源名。

13.synchronized鎖普通方法和鎖靜態方法?

1.對象鎖鑰匙只能有一把才能互斥,才能保證共享變量的惟一性
2.在靜態方法上的鎖,和 實例方法上的鎖,默認不是一樣的,若是同步須要制定兩把鎖同樣。
3.關於同一個類的方法上的鎖,來自於調用該方法的對象,若是調用該方法的對象是相同的,那麼鎖必然相同,不然就不相同。好比 new A().x() 和 newA().x(),對象不一樣,鎖不一樣,若是A的單利的,就能互斥。
4.靜態方法加鎖,能和全部其餘靜態方法加鎖的 進行互斥。
5.靜態方法加鎖,和xx.class 鎖效果同樣,直接屬於類的。

2、多線程

一、線程有幾種狀態?之間是如何切換的?

答:新建狀態、就緒狀態、運行狀態、阻塞狀態死亡狀態。主要是經過獲取鎖標記來獲取對該資源的使用權限,當對象調用了start()進入到就緒狀態,進入就緒後,當該對象被操做系統選中,得到CPU時間片就會進入運行狀態;接下來的狀態切換就會比較複雜,主要經過線程調用不一樣的方法,就會切換不一樣的運行狀態。

二、volatile的做用(兩點),volatile的原理與應用場景。

答:volatile讓變量每次在使用的時候,都從主存中取。(1.將當前處理器緩存行的數據會寫回到系統內存,2.這個寫回內存的操做會引發在其餘CPU裏緩存了該內存地址的數據無效。)而不是從各個線程的「工做內存」。volatile具備synchronized關鍵字的「可見性」,可是沒有synchronized關鍵字的「併發正確性」,也就是說不保證線程執行的有序性,volatile變量對於每次使用,線程都能獲得當前volatile變量的最新值。可是volatile變量並不保證併發的正確性。

三、線程安全是什麼?如何作到線程安全?怎麼判斷一個類是否是線程安全?

答:類要成爲線程安全的,首先必須在單線程環境中有正確的行爲。若是一個類實現正確(這是說它符合規格說明的另外一種方式),那麼沒有一種對這個類的對象的操做序列(讀或者寫公共字段以及調用公共方法)可讓對象處於無效狀態,觀察到對象處於無效狀態、或者違反類的任何不可變量、前置條件或者後置條件的狀況。此外,一個類要成爲線程安全的,在被多個線程訪問時,無論運行時環境執行這些線程有什麼樣的時序安排或者交錯,它必須仍然有如上所述的正確行爲,而且在調用的代碼中沒有任何額外的同步。其效果就是,在全部線程看來,對於線程安全對象的操做是以固定的、全局一致的順序發生的。正確性與線程安全性之間的關係很是相似於在描述 ACID(原子性、一致性、獨立性和持久性)事務時使用的一致性與獨立性之間的關係:從特定線程的角度看,由不一樣線程所執行的對象操做是前後(雖然順序不定)而不是並行執行的。

四、線程同步有幾種方式?爲什麼要使用同步?

答: java容許多線程併發控制,當多個線程同時操做一個可共享的資源變量時(如數據的增刪改查), 將會致使數據不許確,相互之間產生衝突,所以加入同步鎖以免在該線程沒有完成操做以前,被其餘線程的調用, 從而保證了該變量的惟一性和準確性。

同步的實現方式總共分爲七種:

1.同步方法 : 即有synchronized關鍵字修飾的方法,因爲java的每一個對象都有一個內置鎖,當用此關鍵字修飾方法時,內置鎖會保護整個方法。在調用該方法前,須要得到內置鎖,不然就處於阻塞狀態。

2.同步代碼塊:即有synchronized關鍵字修飾的語句塊,被該關鍵字修飾的語句塊會自動被加上內置鎖,從而實現同步

3.使用特殊域變量(volatile)實現線程同步 

a.volatile關鍵字爲域變量的訪問提供了一種免鎖機制。

b.使用volatile修飾域至關於告訴虛擬機該域可能會被其餘線程更新。

 c.所以每次使用該域就要從新計算,而不是使用寄存器中的值。

 d.volatile不會提供任何原子操做,它也不能用來修飾final類型的變量。

 4.使用重入鎖實現線程同步.

java.util.concurrent包下的ReentrantLock類是可重入、互斥、實現了Lock接口的鎖,它與使用synchronized方法和快具備相同的基本行爲和語義,而且擴展了其能力.

5.使用局部變量實現線程同步,若是使用ThreadLocal管理變量,則每個使用該變量的線程都得到該變量的副本, 副本之間相互獨立,這樣每個線程均可以隨意修改本身的變量副本,而不會對其餘線程產生影響

6.使用阻塞隊列實現線程同步,前面5種同步方式都是在底層實現的線程同步,可是咱們在實際開發當中,應當儘可能遠離底層結構。使用javaSE5.0版本中新增的java.util.concurrent包將有助於簡化開發。使用LinkedBlockingQueue來實現線程的同步, LinkedBlockingQueue是一個基於已鏈接節點的,範圍任意的blocking queue。隊列是先進先出的順序(FIFO)。

7.使用原子變量實現線程同步,須要使用線程同步的根本緣由在於對普通變量的操做不是原子的。原子操做就是指將讀取變量值、修改變量值、保存變量值當作一個總體來操做,即-這幾種行爲要麼同時完成,要麼都不完成。在java的util.concurrent.atomic包中提供了建立了原子類型變量的工具類,使用該類能夠簡化線程同步。其中AtomicInteger 表能夠用原子方式更新int的值,可用在應用程序中(如以原子方式增長的計數器),但不能用於替換Integer;可擴展Number,容許那些處理機遇數字類的工具和實用工具進行統一訪問。

五、threadlocal的原理

答:ThreadLocal提供了set和get訪問器用來訪問與當前線程相關聯的線程局部變量。當線程中的threadlocalmap是null的時候,會調用createmap建立一個map。同時根據函數參數設置上初始值。也就是說,當前線程的threadlocalmap是在第一次調用set的時候建立map而且設置上相應的值的。在ThreadLocal的set函數中,能夠看到,其中的map.set(this, value);把當前的threadlocal傳入到map中做爲鍵,也就是說,在不一樣的線程的threadlocals變量中,都會有一個以你所聲明的那個線程局部變量threadlocal做爲鍵的key-value。假設說聲明瞭N個這樣的線程局部變量變量,那麼在線程的ThreadLocalMap中就會有n個分別以你的線程局部變量做爲key的鍵值對。

六、synchronized是如何實現的?

答:每一個對象有一個監視器鎖(monitor)。當monitor被佔用時就會處於鎖定狀態,線程執行monitorenter指令時嘗試獲取monitor的全部權,過程以下:

一、若是monitor的進入數爲0,則該線程進入monitor,而後將進入數設置爲1,該線程即爲monitor的全部者。

二、若是線程已經佔有該monitor,只是從新進入,則進入monitor的進入數加1.

3.若是其餘線程已經佔用了monitor,則該線程進入阻塞狀態,直到monitor的進入數爲0,再從新嘗試獲取monitor的全部權。

對於方法的同步,方法的同步並無經過指令monitorenter和monitorexit來完成(理論上其實也能夠經過這兩條指令來實現),不過相對於普通方法,其常量池中多了ACC_SYNCHRONIZED標示符。JVM就是根據該標示符來實現方法的同步的:當方法調用時,調用指令將會檢查方法的 ACC_SYNCHRONIZED 訪問標誌是否被設置,若是設置了,執行線程將先獲取monitor,獲取成功以後才能執行方法體,方法執行完後再釋放monitor。在方法執行期間,其餘任何線程都沒法再得到同一個monitor對象。 其實本質上沒有區別,只是方法的同步是一種隱式的方式來實現,無需經過字節碼來完成。

七、sleep和wait的區別?

答:sleep()方法致使了程序暫停執行指定的時間,讓出cpu給其餘線程,可是他的監控狀態依然保持者,當指定的時間到了又會自動恢復運行狀態。在調用sleep()方法的過程當中,線程不會釋放對象鎖。而當調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法後本線程才進入對象鎖定池準備,獲取對象鎖進入運行狀態。

八、線程池有幾種?各自的應用場景。

答:1.newFixedThreadPool建立一個指定工做線程數量的線程池。每當提交一個任務就建立一個工做線程,若是工做線程數量達到線程池初始的最大數,則將提交的任務存入到池隊列中。

2.newCachedThreadPool建立一個可緩存的線程池。這種類型的線程池特色是:

1).工做線程的建立數量幾乎沒有限制(其實也有限制的,數目爲Interger. MAX_VALUE), 這樣可靈活的往線程池中添加線程。

2).若是長時間沒有往線程池中提交任務,即若是工做線程空閒了指定的時間(默認爲1分鐘),則該工做線程將自動終止。終止後,若是你又提交了新的任務,則線程池從新建立一個工做線程。

3.newSingleThreadExecutor建立一個單線程化的Executor,即只建立惟一的工做者線程來執行任務,若是這個線程異常結束,會有另外一個取代它,保證順序執行(我以爲這點是它的特點)。單工做線程最大的特色是可保證順序地執行各個任務,而且在任意給定的時間不會有多個線程是活動的。

4.newScheduleThreadPool建立一個定長的線程池,並且支持定時的以及週期性的任務執行,相似於Timer。

總結: 

一.FixedThreadPool是一個典型且優秀的線程池,它具備線程池提升程序效率和節省建立線程時所耗的開銷的優勢。可是,在線程池空閒時,即線程池中沒有可運行任務時,它不會釋放工做線程,還會佔用必定的系統資源。

二.CachedThreadPool的特色就是在線程池空閒時,即線程池中沒有可運行任務時,它會釋放工做線程,從而釋放工做線程所佔用的資源。可是,但當出現新任務時,又要建立一新的工做線程,又要必定的系統開銷。而且,在使用CachedThreadPool時,必定要注意控制任務的數量,不然,因爲大量線程同時運行,頗有會形成系統癱瘓。

九、線程池的原理,主要有幾個參數?線程池滿了怎麼辦?

答:一個線程主要包括如下4個部分:

1.線程池管理器(ThreadPool):用於建立並管理線程池,包括 建立線程池,銷燬線程池,添加新任務;
2.工做線程(PoolWorker):線程池中線程,在沒有任務時處於等待狀態,能夠循環的執行任務;
3.任務接口(Task):每一個任務必須實現的接口,以供工做線程調度任務的執行,它主要規定了任務的入口,任務執行完後的收尾工做,任務的執行狀態等;
4.任務隊列(taskQueue):用於存放沒有處理的任務。提供一種緩衝機制。

ThreadPoolExecutor類可設置的參數主要有:
corePoolSize
核心線程數,核心線程會一直存活,即便沒有任務須要處理。當線程數小於核心線程數時,即便現有的線程空閒,線程池也會優先建立新線程來處理任務,而不是直接交給現有的線程處理。
核心線程在allowCoreThreadTimeout被設置爲true時會超時退出,默認狀況下不會退出。
maxPoolSize
當線程數大於或等於核心線程,且任務隊列已滿時,線程池會建立新的線程,直到線程數量達到maxPoolSize。若是線程數已等於maxPoolSize,且任務隊列已滿,則已超出線程池的處理能力,線程池會拒絕處理任務而拋出異常。
keepAliveTime
當線程空閒時間達到keepAliveTime,該線程會退出,直到線程數量等於corePoolSize。若是allowCoreThreadTimeout設置爲true,則全部線程均會退出直到線程數量爲0。
allowCoreThreadTimeout
是否容許核心線程空閒退出,默認值爲false。
queueCapacity
任務隊列容量。從maxPoolSize的描述上能夠看出,任務隊列的容量會影響到線程的變化,所以任務隊列的長度也須要恰當的設置。

十、Semaphore、futureTask?

答:Semaphore【ˈseməfɔ:(r)】就是一個信號量,它的做用是限制某段代碼塊的併發數。Semaphore有一個構造函數,能夠傳入一個int型整數n,表示某段代碼最多隻有n個線程能夠訪問,若是超出了n,那麼請等待,等到某個線程執行完畢這段代碼塊,下一個線程再進入。由此能夠看出若是Semaphore構造函數中傳入的int型整數n=1,至關於變成了一個synchronized了。

FutureTask 表示一個異步運算的任務。FutureTask裏面能夠傳入一個Callable的具體實現類,能夠對這個異步運算的任務的結果進行等待獲取、判斷是否已經完成、取消任務等操做。固然,因爲FutureTask也是Runnable接口的實現類,因此FutureTask也能夠放入線程池中。

十一、submit和execute的區別。

答:execute(Runnable x) 沒有返回值。能夠執行任務,但沒法判斷任務是否成功完成。——實現Runnable接口

submit(Runnable x) 返回一個future。能夠用這個future來判斷任務是否成功完成。——實現Callable接口。

十二、Future接口的幾個主要方法

答:接口邏輯圖

cancel方法主要是是否可中斷來設置state及中斷狀態。

get()方法主要是調用awaitdone方法來阻塞來等待結果,而後根據最終狀態來返回結果或者拋出異常。

isDone()任務是否已經完成。須要注意的是若是任務正常終止、異常或取消,都將返回true 

isCancelled () 任務是否已經取消,任務正常完成前將其取消,則返回 true 

1三、建立線程有幾種方式

答:1.繼承Thread類建立線程類

2.經過Runnable接口建立線程類

3.經過Callable和Future建立線程

1四、可重入鎖是如何實現的

答:http://blog.jobbole.com/108571/

和線程相關的更多問題能夠移步這裏:http://www.jianshu.com/p/64dae9b00eed

3、數據庫

一、MySQL索引原理?爲何是B+樹?有什麼優勢?

MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。提取句子主幹,就能夠獲得索引的本質:索引是一種數據結構。 數據庫查詢是數據庫的主要功能之一,最基本的查詢算法是順序查找(linear search)時間複雜度爲O(n),顯然在數據量很大時效率很低。優化的查找算法如二分查找(binary search)、二叉樹查找(binary tree search)等,雖然查找效率提升了。可是各自對檢索的數據都有要求:二分查找要求被檢索數據有序,而二叉樹查找只能應用於二叉查找樹上,可是數據自己的組織結構不可能徹底知足各類數據結構(例如,理論上不可能同時將兩列都按順序進行組織)。因此,在數據以外,數據庫系統還維護着知足特定查找算法的數據結構。這些數據結構以某種方式引用(指向)數據,這樣就能夠在這些數據結構上實現高級查找算法。這種數據結構就是索引。

通常來講,索引自己也很大,不可能所有存儲在內存中,所以索引每每以索引文件的形式存儲的磁盤上。這樣的話,索引查找過程當中就要產生磁盤I/O消耗,相對於內存存取,I/O存取的消耗要高几個數量級,因此評價一個數據結構做爲索引的優劣最重要的指標就是在查找過程當中磁盤I/O操做次數的漸進複雜度。換句話說,索引的結構組織要儘可能減小查找過程當中磁盤I/O的存取次數。

從使用磁盤I/O次數評價索引結構的優劣性:根據B-Tree的定義,可知檢索一次最多須要訪問h個結點。數據庫系統的設計者巧妙的利用了磁盤預讀原理,將一個結點的大小設爲等於一個頁面,這樣每一個結點只須要一次I/O就能夠徹底載入。爲了達到這個目的,在實際實現B-Tree還須要使用以下技巧:每次新建結點時,直接申請一個頁面的空間,這樣能夠保證一個結點的大小等於一個頁面,加之計算機存儲分配都是按頁對齊的,就實現了一個node只需一次I/O。B-Tree中一次檢索最多須要h-1次I/O(根結點常駐內存),漸進複雜度爲O(h)=O(logdN)。通常實際應用中,出讀d是很是大的數字,一般超過100,所以h很是小。綜上所述,用B-Tree做爲索引結構效率是很是高的。而紅黑樹結構,h明顯要深得多。因爲邏輯上很近的結點(父子結點)物理上可能離得很遠,沒法利用局部性原理。因此即便紅黑樹的I/O漸進複雜度也爲O(h),可是查找效率明顯比B-Tree差得多。B+Tree更適合外存索引,是和內結點出度d有關。從上面分析能夠看到,d越大索引的性能越好,而出度的上限取決於結點內key和data的大小:dmax=floor(pagesize/(keysize+datasize+pointsize))。floor表示向下取整。因爲B+Tree內結點去掉了data域,所以能夠擁有更大的出度,擁有更好的性能。

參考:http://www.cnblogs.com/tgycoder/p/5410057.html

二、事務隔離級別有哪幾種?mysql默認的隔離級別是?髒讀、幻讀、不可重複讀是什麼狀況?

答:事物隔離級別由低到高分別爲Read uncommitted 、Read committed 、Repeatable read 、Serializable。讀取未提交的數據稱之爲髒讀,一個事務只能看見已經提交事務所作的改變稱之爲不可重複讀,指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的「幻影」 行,稱之爲幻讀。

下圖列的是各個事物隔離級別下可能出現的髒讀、不可重複讀、幻讀圖:

Read Uncommitted(讀取未提交內容)
在該隔離級別,全部事務均可以看到其餘未提交事務的執行結果。本隔離級別不多用於實際應用,由於它的性能也不比其餘級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)。
Read Committed(讀取提交內容)
這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它知足了隔離的簡單定義:一個事務只能看見已經提交事務所作的改變。這種隔離級別 也支持所謂的不可重複讀(Nonrepeatable Read),由於同一事務的其餘實例在該實例處理其間可能會有新的commit,因此同一select可能返回不一樣結果。
Repeatable Read(可重讀)
這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到一樣的數據行。不過理論上,這會致使另外一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的「幻影」 行。InnoDB和Falcon存儲引擎經過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。
Serializable(可串行化)
這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭。

 

參考:http://xm-king.iteye.com/blog/770721

三、MVCC原理

答:MVCC全稱是Multi-Version Concurrent Control,即多版本併發控制。在MVCC協議下,每一個讀操做會看到一個一致性的snapshot,而且能夠實現非阻塞的讀。MVCC容許數據具備多個版本,這個版本能夠是時間戳或者是全局遞增的事務ID,在同一個時間點,不一樣的事務看到的數據是不一樣的。在進行寫操做時,將數據copy一份,不會影響原有數據,而後進行修改,修改完成後原子替換掉舊的數據,而讀操做只會讀取原有數據。經過這種方式實現寫操做不會阻塞讀操做,從而優化讀效率。而寫操做之間是要互斥的,而且每次寫操做都會有一次copy,因此只適合讀大於寫的狀況。

優點:使用MVCC多版本併發控制比鎖定模型的主要優勢是在MVCC裏, 對檢索(讀)數據的鎖要求與寫數據的鎖要求不衝突, 因此讀不會阻塞寫,而寫也從不阻塞讀。

四、mysql有哪幾種鎖?

答:共享讀鎖,獨佔寫鎖。根據數據引擎的不一樣,鎖的類型也不同,對於innodb

五、mysql的存儲引擎有哪幾種?區別和各自的適用場景。

六、query cache的配置

七、ACID

原子性、一致性、隔離性、持久性。

八、如何優化慢查詢

答:1.查詢條件帶上索引,

九、最左前綴匹配原則,原理

4、算法

一、一致性哈希的原理

答:一致性哈希算法在1997年由麻省理工學院提出的一種分佈式哈希(DHT)實現算法,設計目標是爲了解決因特網中的熱點(Hot spot)問題,初衷和CARP十分相似。一致性哈希修正了CARP使用的簡 單哈希算法帶來的問題,使得分佈式哈希(DHT)能夠在P2P環境中真正獲得應用。 

一致性hash算法提出了在動態變化的Cache環境中,斷定哈希算法好壞的四個定義:

一、平衡性(Balance):平衡性是指哈希的結果可以儘量分佈到全部的緩衝中去,這樣可使得全部的緩衝空間都獲得利用。不少哈希算法都可以知足這一條件。
二、單調性(Monotonicity):單調性是指若是已經有一些內容經過哈希分派到了相應的緩衝中,又有新的緩衝加入到系統中。哈希的結果應可以保證原有已分配的內容能夠被映射到原有的或者新的緩衝中去,而不會被映射到舊的緩衝集合中的其餘緩衝區。
三、分散性(Spread):在分佈式環境中,終端有可能看不到全部的緩衝,而是隻能看到其中的一部分。當終端但願經過哈希過程將內容映射到緩衝上時,因爲不一樣終端所見的緩衝範圍有可能不一樣,從而致使哈希的結果不一致,最終的結果是相同的內容被不一樣的終端映射到不一樣的緩衝區中。這種狀況顯然是應該避免的,由於它致使相同內容被存儲到不一樣緩衝中去,下降了系統存儲的效率。分散性的定義就是上述狀況發生的嚴重程度。好的哈希算法應可以儘可能避免不一致的狀況發生,也就是儘可能下降分散性。
四、負載(Load):負載問題其實是從另外一個角度看待分散性問題。既然不一樣的終端可能將相同的內容映射到不一樣的緩衝區中,那麼對於一個特定的緩衝區而言,也可能被不一樣的用戶映射爲不一樣 的內容。與分散性同樣,這種狀況也是應當避免的,所以好的哈希算法應可以儘可能下降緩衝的負荷。

在分佈式集羣中,對機器的添加刪除,或者機器故障後自動脫離集羣這些操做是分佈式集羣管理最基本的功能。若是採用經常使用的hash(object)%N算法,那麼在有機器添加或者刪除後,不少原有的數據就沒法找到了,這樣嚴重的違反了單調性原則。接下來主要講解一下一致性哈希算法是如何設計的:

環形Hash空間
按照經常使用的hash算法來將對應的key哈希到一個具備2^32次方個桶的空間中,即0~(2^32)-1的數字空間中。如今咱們能夠將這些數字頭尾相連,想象成一個閉合的環形。以下圖



將數據經過hash算法處理後映射到環上

如今咱們將object一、object二、object三、object4四個對象經過特定的Hash函數計算出對應的key值,而後散列到Hash環上。以下圖:
Hash(object1) = key1;
Hash(object2) = key2;
Hash(object3) = key3;
Hash(object4) = key4;


將機器經過hash算法處理後映射到環上
在採用一致性哈希算法的分佈式集羣中將新的機器加入,其原理是經過使用與對象存儲同樣的Hash算法將機器也映射到環中(通常狀況下對機器的hash計算是採用機器的IP或者機器惟一的別名做爲輸入值),而後以順時針的方向計算,將全部對象存儲到離本身最近的機器中。
假設如今有NODE1,NODE2,NODE3三臺機器,經過Hash算法獲得對應的KEY值,映射到環中,其示意圖以下:
Hash(NODE1) = KEY1;
Hash(NODE2) = KEY2;
Hash(NODE3) = KEY3;

 

經過上圖能夠看出對象與機器處於同一哈希空間中,這樣按順時針轉動object1存儲到了NODE1中,object3存儲到了NODE2中,object二、object4存儲到了NODE3中。在這樣的部署環境中,hash環是不會變動的,所以,經過算出對象的hash值就能快速的定位到對應的機器中,這樣就能找到對象真正的存儲位置了。

機器的刪除與添加
普通hash求餘算法最爲不妥的地方就是在有機器的添加或者刪除以後會形成大量的對象存儲位置失效,這樣就大大的不知足單調性了,下面來分析一下一致性哈希算法是如何處理的。
1. 節點(機器)的刪除
以上面的分佈爲例,若是NODE2出現故障被刪除了,那麼按照順時針遷移的方法,object3將會被遷移到NODE3中,這樣僅僅是object3的映射位置發生了變化,其它的對象沒有任何的改動。以下圖:

2. 節點(機器)的添加
若是往集羣中添加一個新的節點NODE4,經過對應的哈希算法獲得KEY4,並映射到環中,以下圖:

經過按順時針遷移的規則,那麼object2被遷移到了NODE4中,其它對象還保持這原有的存儲位置。經過對節點的添加和刪除的分析,一致性哈希算法在保持了單調性的同時,仍是數據的遷移達到了最小,這樣的算法對分佈式集羣來講是很是合適的,避免了大量數據遷移,減少了服務器的的壓力。

平衡性
根據上面的圖解分析,一致性哈希算法知足了單調性和負載均衡的特性以及通常hash算法的分散性,但這還並不能當作其被普遍應用的起因,由於還缺乏了平衡性。下面將分析一致性哈希算法是如何知足平衡性的。hash算法是不保證平衡的,如上面只部署了NODE1和NODE3的狀況(NODE2被刪除的圖),object1存儲到了NODE1中,而object二、object三、object4都存儲到了NODE3中,這樣就照成了很是不平衡的狀態。在一致性哈希算法中,爲了儘量的知足平衡性,其引入了虛擬節點。
——「虛擬節點」( virtual node )是實際節點(機器)在 hash 空間的複製品( replica ),一實際個節點(機器)對應了若干個「虛擬節點」,這個對應個數也成爲「複製個數」,「虛擬節點」在 hash 空間中以hash值排列。
以上面只部署了NODE1和NODE3的狀況(NODE2被刪除的圖)爲例,以前的對象在機器上的分佈很不均衡,如今咱們以2個副本(複製個數)爲例,這樣整個hash環中就存在了4個虛擬節點,最後對象映射的關係圖以下:

根據上圖可知對象的映射關係:object1->NODE1-1,object2->NODE1-2,object3->NODE3-2,object4->NODE3-1。經過虛擬節點的引入,對象的分佈就比較均衡了。那麼在實際操做中,正真的對象查詢是如何工做的呢?對象從hash到虛擬節點到實際節點的轉換以下圖:



「虛擬節點」的hash計算能夠採用對應節點的IP地址加數字後綴的方式。例如假設NODE1的IP地址爲192.168.1.100。引入「虛擬節點」前,計算 cache A 的 hash 值:
Hash(「192.168.1.100」);
引入「虛擬節點」後,計算「虛擬節」點NODE1-1和NODE1-2的hash值:
Hash(「192.168.1.100#1」); // NODE1-1
Hash(「192.168.1.100#2」); // NODE1-2

轉自:http://blog.csdn.net/cywosp/article/details/23397179

二、手寫二分查找,快速排序

答:

三、手寫LRU算法

四、兩個鏈表找交點

五、兩個無限長的數字求和

六、手寫生產者消費者demo

七、256M內存排序2G大小的文件

八、求數組最大子序列

九、1*2*3*4***50,一共有多少個0?

答:0是5跟偶數相乘獲得的,因此有幾個0就看有幾個5 50內5的倍數有10個,因此能獲得10個0.可是25的倍數裏有兩個5,還要再加兩個 總共是12個。

5、操做系統與計算機網絡

一、如何從訪問日誌中找出量最大的10個ip?awk語句瞭解嗎?

二、jstack,jstat,jmap,jheap命令瞭解嗎,如何使用?

三、系統負載狀況如何查看?

四、網絡分層協議瞭解嗎?

五、tcp三次握手,四次揮手瞭解嗎?

六、aio,bio,nio的區別

七、select,poll,epoll的區別?

八、io模型有哪些?

6、開源框架與組件

這部分主要根據簡歷以及項目的實際狀況來問。

一、對spring瞭解嗎?ioc,aop,transaction註解

二、spingmvc瞭解嗎?

三、Redis與memcache的區別

四、redis持久化策略,rdb與aof的區別與應用場景

五、memcached的內存是如何分配的?一致性哈希原理

六、mq的原理與應用場景,mq是如何保證不丟消息的?

七、tomcat的原理,主要運用了哪些設計模式?

八、redis與memcached內存分別是如何回收的?

九、guava的緩存是怎麼實現的?

十、Spring AOP 原理

AOP的實現原理就是動態的生成代理類,代理類的執行過程爲:執行咱們增長的代碼(例如方法日誌記錄)—-> 回調原方法 ——> 增長的代碼邏輯。
Spring AOP 動態代理可能採用JDK動態代理或CGlib動態生成代理類兩種方式中的一種,決定用哪種方式的判斷標準就是被切面的類是否有其實現的接口,若是有對應的接口,則採用JDK動態代理,不然採用CGlib字節碼生成機制動態代理方式。代理模式是一種經常使用的設計模式,其目的就是爲其餘對象提供一個代理以控制對某個對象的訪問。代理類負責爲委託類預處理消息,過濾消息並轉發消息,以及進行消息被委託類執行後的後續處理。代理類和委託類實現相同的接口,因此調用者調用代理類和調用委託類幾乎感受不到差異。動態代理的意思是運行時動態生成代理實現類,因爲JVM的機制,須要直接操做字節碼,生成新的字節碼文件,也就是.class 文件。
JDK動態代理
JDK動態代理模式採用sun的ProxyGenerator的字節碼框架。要說明的是,只有實現了接口的類才能使用 JDK 動態代理技術,實現起來也比較簡單。
1. 只要實現 InvocationHandler 接口,並覆寫 invoke方法便可。Proxy.newProxyInstance方法用於動態生成實際生成的代理類,三個參數依次爲被代理類的類加載器、被代理類所實現的接口和當前代理攔截器。
覆寫的 invoke 中能夠加入咱們增長的業務邏輯,而後回調原方法。
jdkProxy.bind 會生成一個實際的代理類,這個生成過程是利用的字節碼生成技術,生成的代理類實現了IWorker 接口,咱們調用這個代理類的 dowork 方法的時候,實際在代理類中是調用了 JdkProxy (也就是咱們實現的這個代理攔截器)的 invoke 方法,接着執行咱們實現的 invoke 方法,也就執行了咱們加入的邏輯,從而實現了切面編程的需求。
咱們把動態生成的代理類字節碼文件反編譯一下,也就明白了。
CGLIB動態代理
CGlib庫使用了ASM這一個輕量但高性能的字節碼操做框架來轉化字節碼,它能夠在運行時基於一個類動態生成它的子類。無論有沒有接口,凡是類均可以被繼承,擁有這樣的特色,原則上來講,它能夠對任何類進行代碼攔截,從而達到切面編程的目的。
CGlib 不須要咱們很是瞭解字節碼文件(.class 文件)的格式,經過簡單的 API 便可實現字節碼操做。
基於這樣的特色,CGlib 被普遍用於如 Spring AOP 等基於 代理模式的AOP框架中。
CGlib不支持final類,CGlib 的執行速度比較快,可是建立速度比較慢,因此若是兩種動態代理都適用的場景下,有大量動態代理類建立的場景下,用 JDK 動態代理模式,不然能夠用 CGlib 。

jdk動態代理是由Java內部的反射機制來實現的,cglib動態代理底層則是藉助asm來實現的。總的來講,反射機制在生成類的過程當中比較高效,而asm在生成類以後的相關執行過程當中比較高效(能夠經過將asm生成的類進行緩存,這樣解決asm生成類過程低效問題)。還有一點必須注意:jdk動態代理的應用前提,必須是目標類基於統一的接口。若是沒有上述前提,jdk動態代理不能應用。

7、場景設計與架構

一、秒殺場景,如何作技術選型?

二、設計一個支持高併發的服務,寫出核心代碼

三、高併發與高可用如何實現?

四、服務降級怎麼作?限流、限速、超時重試、熔斷、自恢復、分別如何實現?

五、什麼是微服務?有什麼好處?爲何要這麼作?

六、CAP理論是什麼?項目中的哪些場景用到了CAP理論?

七、BASE理論是什麼?

八、何時應該使用mq?

8、其餘

一、平時都經過什麼方式學習技術?

二、最近學的一個知識點是什麼?

三、對帶人有什麼經驗?

四、最熟悉的一個項目是什麼?

五、跳槽的時候,你最看重什麼?

六、爲何跳槽?爲何選擇咱們公司?

相關文章
相關標籤/搜索