我的知識點

數組 :數據存儲區間是連續的,佔用內存嚴重,空間複雜度大。數組的二分查找時間複雜度比較小。數組特點:查詢容易,插入和刪除困難
鏈表: 鏈表存儲區間離散,佔用內存比較寬鬆,空間複雜度小,但是時間複雜度大。鏈表特點:查詢困難,插入和刪除容易。

1.HashMap的源碼,實現原理,JDK8中對HashMap做了怎樣的優化?

哈希表是由數組和鏈表組成的,一個長度爲16的數組中,每個元素存儲的是一個鏈表的頭結點。元素是按照hash(key)%len,也就是元素的key的哈希值對數組長度取模得到。hashMap存儲數據的容器就是一個線性數組,hashmap裏面實現了一個靜態內部類Entry,其重要的屬性有key,value,next。entry是hashMap的一個基礎bean,map裏面的數據都存儲在Entry[]裏面。

2.hashMap的擴容機制?

當向容器添加元素的時候,會判斷當前容器的元素個數,如果大於等於閥值–當前數組的長度乘以加載因子的值時候,就要自動擴容。
java數組是無法自動擴容的,數組擴容是用一個新的數組代替已有容量小的數組。

hashmap擴容會將長度擴容到之前的2倍。

  1. hashMap,hashTable,ConsurrentHashMap三者的區別?

HashMap沒有同步考慮,hashTable使用了Synchornized。單線程使用hashMap提高效率,多線程使用hashTable保證安全。
HashMap是Hashtable的輕量級實現(非線程安全的實現),他們都完成了Map接口,主要區別在於HashMap允許空(null)鍵值(key),由於非線程安全,效率上可能高於Hashtable。
HashMap允許將null作爲一個entry的key或者value,而Hashtable不允許。
HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因爲contains方法容易讓人引起誤解。
Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map interface的一個實現。
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個線程訪問Hashtable時,不需要自己爲它的方法實現同步,而HashMap 就必須爲之提供外同步。
Hashtable和HashMap採用的hash/rehash算法都大概一樣,所以性能不會有很大的差異。

ConcurrentHashMap將hash表分爲16個桶(默認值),諸如get,put,remove等常用操作只鎖當前需要用到的桶。試想,原來只能一個線程進入,現在卻能同時16個寫線程進入(寫線程才需要鎖定,而讀線程幾乎不受限制,之後會提到),併發性的提升是顯而易見的。
更令人驚訝的是ConcurrentHashMap的讀取併發,因爲在讀取的大多數時候都沒有用到鎖定,所以讀取操作幾乎是完全的併發操作,而寫操作鎖定的粒度又非常細,比起之前又更加快速(這一點在桶更多時表現得更明顯些)。只有在求size等操作時才需要鎖定整個表。而在迭代時,ConcurrentHashMap使用了不同於傳統集合的快速失敗迭代器(見之前的文章《JAVA API備忘—集合》)的另一種迭代方式,我們稱爲弱一致迭代器。在這種迭代方式中,當iterator被創建後集合再發生改變就不再是拋出ConcurrentModificationException,取而代之的是在改變時new新的數據從而不影響原有的數據,iterator完成後再將頭指針替換爲新的數據,這樣iterator線程可以使用原來老的數據,而寫線程也可以併發的完成改變,更重要的,這保證了多個線程併發執行的連續性和擴展性,是性能提升的關鍵。
4. java 4中權限修飾符的作用範圍。

public 修飾的成員,在同類,同包,子類,其他包中都可以訪問

protected 修飾的成員,在同類,同包,子類中可以訪問,但是在其他包下不可以訪問。

default 修飾的成員,在同類,同包中可以訪問,但是在其他包中不管是不是子類都不能訪問

private修飾的成員,只能在同類中被訪問。‘

public 和default都可以修飾類和成員變量,而protected和private都不可以修飾類。

5 . object類中的方法?

5.1 toString()
5.2 equals()    
5.3 hashCode()
5.4 notify()
5.5 notifyAll()
5.6 getClass()
5.7 wait()

6 .接口和抽象類的區別,注意JDK8的接口可以有實現?

    6.1 接口可以多實現,抽象類只能單獨被繼承,
    6.2 抽象類必須加abstract修飾,接口默認是public abstract
    6.3 抽象類可以有構造方法,接口不能含有構造方法

7 . java實現動態代理的兩種方式:

    7.1 JDK動態代理
    7.2 cglib產生代理

這兩種方法各有好壞。jdk動態代理是由java內部的反射機制生成字節碼並生成對象來實現的,而cglib代理底層是藉助asm來實現的,這個asm就是一個java字節碼操縱框架,它能用來動態生成類或者增強類的功能,ASM從類文件中讀入信息後,改變類的行爲,分析類的信息,這就跟aop實現方式中的靜態織入的是一樣的,就是相當於把切面織入類的字節碼文件中,以此達到攔截的作用。一般jdk動態代理用於目標類都是基於統一的接口,cglib多用於對類的代理,這些類不需要實現統一的接口。

  1. 傳值和傳引用的區別,Java是怎麼樣的,有沒有傳值引用?

    java所有操作都是傳值操作。 
    

    值傳遞:方法調用時,實際參數把它的值的副本傳遞給對應的形式參數。特點:此時內存中存在兩個相等的基本類型,即實際參數和形式參數,後面方法中的操作都是對形參這個值的修改,不影響實際參數的值。

  2. 一個ArrayList在循環過程中刪除,會不會出問題,爲什麼?

    list 有序,可重複。遍歷刪除,arraylist的長度就變化了, 會出現數組下標越界。使用迭代器iterator()。

10 . @transactional註解在什麼情況下會失效,爲什麼?

    編譯時異常不會回滾(超時,網絡異常,文件肚子餓),運行時異常會回滾(空指針,數組下標越界,1/0)。

11 . b+樹

 每個節點有多個child,一顆b+樹包含根節點,內部節點,葉子結點。根節點可能是一個葉子節點,也可能是一個包含兩個或兩個以上的孩子節點的節點。
 B+樹通常用於數據庫和操作系統的文件系統中,能夠保持數據穩定有序,插入和修改擁有較穩定的對數時間複雜度,B+樹自底向上插入。

12 . 一致性hash算法

一致性hash作爲一個負載均衡算法,可以用在分佈式緩存、數據庫的分庫分表等場景中,還可以應用在負載均衡器中作爲作爲負載均衡算法。在有多臺服務器時,對於某個請求資源通過hash算法,映射到某一個臺服務器,當增加或減少一臺服務器時,可能會改變這些資源對應的hash值,這樣可能導致一部分緩存或數據失效了。一致性hash就是儘可能在將同一個資源請求路由到同一臺服務器中。
普通hash,當我們增加一個節點的時候,所有數據都要重新遷移。一致性hash,首先把2的32次方抽象成一個環。比如說集羣有四個節點,他們會根據hash後映射到環上的某個點,在存儲數據的時候這些點按照順時針方向,找到距離自己最近的一個物理節點就是要存儲的節點。當增加一個節點的時候,只會影響這個節點前後兩個節點之間的數據,其他數據不受影響。如果出現負載不均衡的情況,增加虛擬節點,然後把這些虛擬節點映射到物理節點。

13 . jvm的內存結構

JVM內存結構主要有三大塊:堆內存、方法區和棧。
堆內存是JVM中最大的一塊由年輕代和老年代組成,new創建的實例化對象及數組,是存放在堆內存中的,用完之後靠垃圾回收機制不定期自動消除。
方法區存儲類信息、常量、靜態變量等數據,是線程共享的區域,
棧又分爲java虛擬機棧和本地方法棧主要用於方法的執行。基本數據類型、局部變量都是存放在棧內存中的,用完就消失。

14 . Java類加載的過程?

    14.1 加載  獲取類的二進制字節流,將這個字節流所代表的靜態存儲結構轉化爲方法區的運行

時結構,在java堆中生成一個代表這個類的java.lang.Class對象>,作爲方法區的數據訪問入口。
14.2 驗證 驗證class獨享的字節流包含的信息是否符合jvm要求,不會危害jvm的安全
14.3 準備 類變量分配內存並設置類變量的初始值
14.4 解析 虛擬機將常量池的符號引用替換爲直接引用的過程
14.5 初始化 執行類中定義的java代碼
15 . JVM調優,常用JVM參數配置

    15.1 打開GC各種日誌(每次執行GC信息都能打印,獲得執行時間,空間大小)
    15.2 類加載監控:(監控類加載的順序)
    15.3 堆的分配參數
    15.4 棧的分配參數

16 . Java實現多線程有哪幾種方式?

16.1 繼承Thread類實現多線程
16.2 實現Runnable接口方式實現多線程
16.3 使用ExecutorService、Callable、Future實現有返回結果的多線程

java1.5 引入的有返回有返回結果的線程,前兩個的缺點就是沒有返回結果。

17 . 線程池的參數有哪些,在線程池創建一個線程的過程?

 corePoolSize : 核心池的大小
 maximumPoolSize : 線程池的最大線程數
 keepAliveTime : 表示線程沒有任務執行時最多保持多久時間會終止
 unit : 參數keepAliveTime的時間單位
 workQueue : 一個阻塞隊列,用來存儲等待執行的任務
 threadFactory:線程工廠,主要用來創建線程
 handler:表示當拒絕處理任務時的策略

18 . volitile關鍵字的作用,原理?

一旦一個共享變量(類的成員變量、類的靜態成員變量)被volatile修飾之後,那麼就具備了兩層語義:
 1)保證了不同線程對這個變量進行操作時的可見性,即一個線程修改了某個變量的值,這新值對其他線程來說是立即可見的。
  2)禁止進行指令重排序。

原理涉及到java的內存模型。
19 . synchronized關鍵字的用法,優缺點?

jvm實現的一個鎖機制。是一種同步鎖。
synchronized是不錯,但它並不完美。它有一些功能性的限制:
    --它無法中斷一個正在等候獲得鎖的線程;
    -也無法通過投票得到鎖,如果不想等下去,也就沒法得到鎖;
    --同步還要求鎖的釋放只能在與獲得鎖所在的堆棧幀相同的堆棧幀中進行,多數情況下,這沒問題(而且與異常處理交互得很好),但是,確實存在一些非塊結構的鎖定更合適的情況

20 . 線程的狀態?

新生狀態
就緒狀態
運行狀態
阻塞狀態
死亡狀態

21 . sleep和wait的區別?

對於sleep()方法,我們首先要知道該方法是屬於Thread類中的。而wait()方法,則是屬於Object類中的。
sleep()方法導致了程序暫停執行指定的時間,讓出cpu該其他線程,但是他的監控狀態依然保持者,當指定的時間到了又會自動恢復運行狀態。在調用sleep()方法的過程中,線程不會釋放對象鎖。
而當調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法後本線程才進入對象鎖定池準備。

22 . notify和notifyall的區別?

notify只會通知一個在等待的對象,而notifyAll會通知所有在等待的對象,並且所有對象都會繼續運行。

23 . ThreadLocal的瞭解,實現原理?

    總結:ThreadLocal不是爲了解決多線程訪問共享變量,而是爲每個線程創建一個單獨的變量副本,提供了保持對象的方法和避免參數傳遞的複雜性。
    ThreadLocal可以看做是一個容器,容器裏面存放着屬於當前線程的變量。ThreadLocal類提供了四個對外開放的接口方法,這也是用戶操作ThreadLocal類的基本方法:
    (1) void set(Object value)設置當前線程的線程局部變量的值。 
    (2) public Object get()該方法返回當前線程所對應的線程局部變量。 
    (3) public void remove()將當前線程局部變量的值刪除,目的是爲了減少內存的佔用,該方法是JDK 5.0新增的方法。需要指出的是,當線程結束後,對應該線程的局部變量將自動被垃圾回收,所以顯式調用該方法清除線程的局部變量並不是必須的操作,但它可以加快內存回收的速度。  

24 . 常見的數據庫優化手段

    24.1 減少數據訪問(減少磁盤訪問)
    24.2 返回更少的數據(減少網絡傳輸或磁盤訪問)
    24.3 減少交互次數(減少網絡傳輸)
    24.4 減少cpu及內存開銷()
    24.5 利用更多資源(增加資源)

25 . 索引的優缺點,什麼字段上建立索引?

25.1 索引就像是書的目錄,是與表或視圖關聯的磁盤上結構,可以加快從表或視圖中檢索行的速度。索引中包含由表或視圖中的一列或多列生成的鍵。這些鍵存儲在一個結構(BTree)中,使SQL可以快速有效地查找與鍵值關聯的行。

25.2. 爲什麼要建立索引,即索引的優點:

    ①  建立索引的列可以保證行的唯一性,生成唯一的rowId

    ②  建立索引可以有效縮短數據的檢索時間

    ③  建立索引可以加快表與表之間的連接

    ④  爲用來排序或者是分組的字段添加索引可以加快分組和排序順序

   25.3. 索引的缺點:

① 創建索引和維護索引需要時間成本,這個成本隨着數據量的增加而加大

② 創建索引和維護索引需要空間成本,每一條索引都要佔據數據庫的物理存儲空間,數據量越大,佔用空間也越大(數據表佔據的是數據庫的數據空間)
③ 會降低表的增刪改的效率,因爲每次增刪改索引需要進行動態維護,導致時間變長

    25.4. 什麼樣的表跟列要建立索引:
    ①  總的來說就是數據量大的,經常進行查詢操作的表要建立索引
    ④  用於排序的字段可以添加索引,用於分組的字段應當視情況看是否需要添加索引。
    ⑤  添加多列索引的時候,對應的多條件查詢可以觸發該索引的同時,索引最左側的列的單條件查詢也可以觸發。
    ⑥  如果有些表註定只會進行查詢所有,也就沒必要添加索引,因爲查詢全部只能進行全量搜索即掃描全表。

26 . 索引的原理:

    索引的原理大致概括爲以空間換時間,數據庫在未添加索引的時候進行查詢默認的是進行全量搜索,也就是進行全局掃描,有多少條數據就要進行多少次查詢,然後找到相匹配的數據就把他放到結果集中,直到全表掃描完。而建立索引之後,會將建立索引的KEY值放在一個n叉樹上(BTree)。因爲B樹的特點就是適合在磁盤等直接存儲設備上組織動態查找表,每次以索引進行條件查詢時,會去樹上根據key值直接進行搜索,次數約爲log總條數,底數爲頁面存儲數,例如一個100萬數據的表,頁面存儲數爲100,那麼有索引的查詢次數爲3次log1000000100,但是全量搜索爲100萬次搜索,這種方式類似於二分法,但是這個是n分法。

27 . 數據庫連接池?

27.1 應用程序直接獲取數據裏連接的缺點: 用戶每次請求都需要向數據庫獲得鏈接,而數據庫創建連接通常需要消耗相對較大的資源,創建時間也較長。假設網站一天10萬訪問量,數據庫服務器就需要創建10萬次連接,極大的浪費數據庫的資源,並且極易造成數據庫服務器內存溢出、拓機

27.2 使用數據庫連接池優化程序性能 : 數據庫連接池負責分配,管理和釋放數據庫連接,它允許應用程序重複使用一個現有的數據庫連接,而不是重新建立一個。
數據庫連接池在初始化時將創建一定數量的數據庫連接放到連接池中, 這些數據庫連接的數量是由最小數據庫連接數來設定的.無論這些數據庫連接是否被使用,連接池都將一直保證至少擁有這麼多的連接數量.連接池的最大數據庫連接數量限定了這個連接池能佔有的最大連接數,當應用程序向連接池請求的連接數超過最大連接數量時,這些請求將被加入到等待隊列中.

數據庫連接池的最小連接數和最大連接數的設置要考慮到以下幾個因素:
最小連接數:是連接池一直保持的數據庫連接,所以如果應用程序對數據庫連接的使用量不大,將會有大量的數據庫連接資源被浪費.
最大連接數:是連接池能申請的最大連接數,如果數據庫連接請求超過次數,後面的數據庫連接請求將被加入到等待隊列中,這會影響以後的數據庫操作
如果最小連接數與最大連接數相差很大:那麼最先連接請求將會獲利,之後超過最小連接數量的連接請求等價於建立一個新的數據庫連接.不過,這些大於最小連接數的數據庫連接在使用完不會馬上被釋放,他將被放到連接池中等待重複使用或是空間超時後被釋放.

28 . durid的常用配置?

29 . TCP,UDP區別?
TCP 優點:穩定,可靠。三次握手建立連接才能通信。tcp具有確認,窗口,重傳,擁塞控制機制。
缺點:慢,效率低,佔用資源高。
UDP: 傳輸速率快,但是不安全,不可靠,可能丟包。
1.基於連接與無連接;
2.對系統資源的要求(TCP較多,UDP少);
3.UDP程序結構較簡單;
4.流模式與數據報模式 ;
5.TCP保證數據正確性,UDP可能丟包,TCP保證數據順序,UDP不保證。

30 . spring中用到哪些設計模式?

1.工廠模式,這個很明顯,在各種BeanFactory以及ApplicationContext創建中都用到了;

2.模版模式,這個也很明顯,在各種BeanFactory以及ApplicationContext實現中也都用到了;

3.代理模式,在Aop實現中用到了JDK的動態代理;

4.單例模式,這個比如在創建bean的時候。

31 . 分佈式事務的控制?

分佈式事務就是指事務的參與者、支持事務的服務器、資源服務器以及事務管理器分別位於不同的分佈式系統的不同節點之上。簡單的說,就是一次大的操作由不同的小操作組成,這些小的操作分佈在不同的服務器上,且屬於不同的應用,分佈式事務需要保證這些小操作要麼全部成功,要麼全部失敗。本質上來說,分佈式事務就是爲了保證不同數據庫的數據一致性。

分佈式事務解決方案:基於XA協議的兩階段提交。XA中大致分爲兩部分:事務管理器和本地資源管理器。其中本地資源管理器往往由數據庫實現,比如Oracle、DB2這些商業數據庫都實現了XA接口。而事務管理器作爲全局的調度者,負責各個本地資源的提交和回滾。

最終一致性: 所謂的消息事務就是基於消息中間件的兩階段提交,本質上是對消息中間件的一種特殊利用,它是將本地事務和發消息放在了一個分佈式事務裏,保證要麼本地操作成功成功並且對外發消息成功,要麼兩者都失敗,開源的RocketMQ就支持這一特性。

32 . 分佈式鎖如何設計?

33 . 分佈式session如何設計?

    基於數據庫的session共享
    基於緩存的session共享
    基於文件系統

34 . zookeeper的負載均衡算法有哪些?

35 . redis和memcached的區別?

1、Redis和Memcache都是將數據存放在內存中,都是內存數據庫。不過memcache還可用於緩存其他東西,例如圖片、視頻等等;
2、Redis不僅僅支持簡單的k/v類型的數據,同時還提供list,set,hash等數據結構的存儲;
3、虛擬內存–Redis當物理內存用完時,可以將一些很久沒用到的value 交換到磁盤
4、過期策略–memcache在set時就指定,例如set key1 0 0 8,即永不過期。Redis可以通過例如expire 設定,例如expire name 10;
5、分佈式–設定memcache集羣,利用magent做一主多從;redis可以做一主多從。都可以一主一從;
6、存儲數據安全–memcache掛掉後,數據沒了;redis可以定期保存到磁盤(持久化);
7、災難恢復–memcache掛掉後,數據不可恢復; redis數據丟失後可以通過aof恢復;
8、Redis支持數據的備份,即master-slave模式的數據備份

redis、memcache、mongoDB 對比
從以下幾個維度,對redis、memcache、mongoDB 做了對比,
1、性能
都比較高,性能對我們來說應該都不是瓶頸
總體來講,TPS方面redis和memcache差不多,要大於mongodb
2、操作的便利性
memcache數據結構單一
redis豐富一些,數據操作方面,redis更好一些,較少的網絡IO次數
mongodb支持豐富的數據表達,索引,最類似關係型數據庫,支持的查詢語言非常豐富

3、內存空間的大小和數據量的大小
redis在2.0版本後增加了自己的VM特性,突破物理內存的限制;可以對key value設置過期時間(類似memcache)
memcache可以修改最大可用內存,採用LRU算法
mongoDB適合大數據量的存儲,依賴操作系統VM做內存管理,吃內存也比較厲害,服務不要和別的服務在一起

5、可靠性(持久化)

對於數據持久化和數據恢復,

redis支持(快照、AOF):依賴快照進行持久化,aof增強了可靠性的同時,對性能有所影響

memcache不支持,通常用在做緩存,提升性能;

MongoDB從1.8版本開始採用binlog方式支持持久化的可靠性

6、數據一致性(事務支持)

Memcache 在併發場景下,用cas保證一致性

redis事務支持比較弱,只能保證事務中的每個操作連續執行

mongoDB不支持事務

7、數據分析

mongoDB內置了數據分析的功能(mapreduce),其他不支持

8、應用場景
redis:數據量較小的更性能操作和運算上

memcache:用於在動態系統中減少數據庫負載,提升性能;做緩存,提高性能(適合讀多寫少,對於數據量比較大,可以採用sharding)

MongoDB:主要解決海量數據的訪問效率問題

36 . redis支持哪些數據結構?

String、list,hash,zset,set

31 . redis是單線程的麼,所有的工作都是單線程麼?

cpu不是redis的瓶頸,redis的瓶頸來源於內存還有網絡帶寬。單線程更容易實現。

redis速度快的原因:1.絕大多數操作都是內存操作。2. 單線程實現,避免了不必要的上下文切換。3. 非阻塞IO

32 . redis的哨兵模式,一個key值如何在redis集羣中找到存儲在哪裏?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章