Java面試題總結

分佈式事務解決方案

 

線程池java

 

分佈式鎖mysql

 

Spring IOC和AOP程序員

 

Spring BeanFactory 算法

 

Jvm原理和垃圾回收機制sql

 

Spring事務的1+3種實現方式、7種傳播行爲、4種隔離級別數據庫

1)編程式事務管理:調用beginTransaction()、commit()、rollback()等事務管理相關的方法 
2)聲明式事務管理:基於TransactionProxyFactoryBean的聲明式事務管理:–不多使用 
3)聲明式事務管理:基於AspectAOP聲明式事務管理:–常使用 
4)聲明式事務管理:基於註解@Transaction的聲明式事務管理:–常用
1)propagation_requierd:若是當前沒有事務,就新建一個事務,若是已存在一個事務中,加入到這個事務中,這是最多見的選擇。Spring默認的事務傳播行爲 
2)propagation_supports:支持當前事務,若是沒有當前事務,就以非事務方法執行。 
3)propagation_mandatory:使用當前事務,若是沒有當前事務,就拋出異常。 
4)propagation_required_new:新建事務,若是當前事務存在,把當前事務掛起。 
5)propagation_not_supported:以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。 
6)propagation_never:以非事務方式執行操做,若是當前事務存在則拋出異常。 
7)propagation_nested:若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則執行與propagation_required相似的操做。 
注:Spring事務的嵌套解析—-Spring的事務傳播策略在內部方法調用時將不起做用
Spring的事務傳播策略在兩個不一樣的Service調用時會起做用 
class ServiceA { 
void methodA() {ServiceB.methodB();} 
class ServiceB { 
void methodB() {… } 
若是ServiceA.methodA已經起了事務,調用ServiceB.methodB時,B不新起事務,若是A沒有事務,則B新建一個事務,B回滾A也回滾。
1)讀未提交:T1讀取T2未提交的東西,會出現髒讀,不可重複讀,幻讀 
2)讀已提交:mysql默認,會出現不可重複讀和幻讀 
3)可重複讀:針對的是update操做,可是會出現幻讀現象,幻讀針對的是insert操做 
4)串行化:解決了髒讀、不可重複讀和幻讀,可是效率比較低

Spring Bean的生命週期 編程

    一、實例化一個Bean--也就是咱們常說的new;後端

    二、按照Spring上下文對實例化的Bean進行配置--也就是IOC注入;數組

    三、若是這個Bean已經實現了BeanNameAware接口,會調用它實現的setBeanName(String)方法,此處傳遞的就是Spring配置文件中Bean的id值緩存

    四、若是這個Bean已經實現了BeanFactoryAware接口,會調用它實現的setBeanFactory(setBeanFactory(BeanFactory)傳遞的是Spring工廠自身(能夠用這個方式來獲取其它Bean,只需在Spring配置文件中配置一個普通的Bean就能夠);

    五、若是這個Bean已經實現了ApplicationContextAware接口,會調用setApplicationContext(ApplicationContext)方法,傳入Spring上下文(一樣這個方式也能夠實現步驟4的內容,但比4更好,由於ApplicationContext是BeanFactory的子接口,有更多的實現方法);

    六、若是這個Bean關聯了BeanPostProcessor接口,將會調用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor常常被用做是Bean內容的更改,而且因爲這個是在Bean初始化結束時調用那個的方法,也能夠被應用於內存或緩存技術;

    七、若是Bean在Spring配置文件中配置了init-method屬性會自動調用其配置的初始化方法。

    八、若是這個Bean關聯了BeanPostProcessor接口,將會調用postProcessAfterInitialization(Object obj, String s)方法、;

    注:以上工做完成之後就能夠應用這個Bean了,那這個Bean是一個Singleton的,因此通常狀況下咱們調用同一個id的Bean會是在內容地址相同的實例,固然在Spring配置文件中也能夠配置非Singleton,這裏咱們不作贅述。

    九、當Bean再也不須要時,會通過清理階段,若是Bean實現了DisposableBean這個接口,會調用那個其實現的destroy()方法;

    十、最後,若是這個Bean的Spring配置中配置了destroy-method屬性,會自動調用其配置的銷燬方法

 

事務的ACID是指什麼

原子性 (atomicity):強調事務的不可分割.
一致性 (consistency):事務的執行的先後數據的完整性保持一致.
隔離性 (isolation):一個事務執行的過程當中,不該該受到其餘事務的干擾
持久性(durability) :事務一旦結束,數據就持久到數據庫

事務隔離級別?
DEFAULT 這是一個PlatfromTransactionManager默認的隔離級別,使用數據庫默認的事務隔離級別
未提交讀(read uncommited) :髒讀,不可重複讀,虛讀都有可能發生
已提交讀 (read commited):避免髒讀。可是不可重複讀和虛讀有可能發生
可重複讀 (repeatable read) :避免髒讀和不可重複讀.可是虛讀有可能發生
串行化的 (serializable) :避免以上全部讀問題

事務傳播機制?
保證同一個事務中
PROPAGATION_REQUIRED 支持當前事務,若是不存在 就新建一個(默認)
PROPAGATION_SUPPORTS 支持當前事務,若是不存在,就不使用事務
PROPAGATION_MANDATORY 支持當前事務,若是不存在,拋出異常
保證沒有在同一個事務中
PROPAGATION_REQUIRES_NEW 若是有事務存在,掛起當前事務,建立一個新的事務
PROPAGATION_NOT_SUPPORTED 以非事務方式運行,若是有事務存在,掛起當前事務
PROPAGATION_NEVER 以非事務方式運行,若是有事務存在,拋出異常
PROPAGATION_NESTED 若是當前事務存在,則嵌套事務執行

抽象類和接口的區別

a.一個類只能繼承單個類,可是能夠實現多個接口

b.抽象類中能夠有構造方法,接口中不能有構造方法

c.抽象類中的全部方法並不必定要是抽象的,你能夠選擇在抽象類中實現一些基本的方法。而接口要求全部的方法都必須是抽象的

d.抽象類中能夠包含靜態方法,接口中不能夠

e.抽象類中能夠有普通成員變量,接口中不能夠

 

訪問修飾符public,private,protected,以及不寫(默認)時的區別?

修飾符 當前類 同 包 子 類 其餘包
public
protected ×
default × ×
private × × ×

String和StringBuilder、StringBuffer的區別?

 String和StringBuffer/StringBuilder,它們能夠儲存和操做字符串。其中String是隻讀字符串,也就意味着String引用的字符串內容是不能被改變的。

而StringBuffer/StringBuilder類表示的字符串對象能夠直接進行修改。StringBuilder是Java 5中引入的,它和StringBuffer的方法徹底相同,區別在於它是在單線程環境下使用的,由於它的全部方面都沒有被synchronized修飾,所以它的效率也比StringBuffer要高

 

String a = "str"; String b = new String("str");問 a == b , a.equals(b) 的值是true仍是false?
==:比較引用類型比較的是地址值是否相同
equals:比較引用類型默認也是比較地址值是否相同,而String類重寫了equals()方法,比較的是內容是否相同
String a = "str"; ,"str" 存到方法區的字符串常量池。而String b = new String("str");,new String() 存到堆中,在指向常量池的"str"。
用 == 時,a指向的是字符串常量池地址,而b指向的是 new String() 堆中存放地址。因此必然false。而String 的equals 是比較內容。因此是 true

Java 中的final關鍵字有哪些用法?

(1)修飾類:表示該類不能被繼承

(2)修飾方法:表示方法不能被重寫

(3)修飾變量:表示變量只能一次賦值之後值不能被修改(常量)

 

闡述final、finally、finalize的區別

- final:修飾符(關鍵字)有三種用法:若是一個類被聲明爲final,意味着它不能再派生出新的子類,即不能被繼承,所以它和abstract是反義詞。將變量聲明爲final,能夠保證它們在使用中不被改變,被聲明爲final的變量必須在聲明時給定初值,而在之後的引用中只能讀取不可修改。被聲明爲final的方法也一樣只能使用,不能在子類中被重寫。
- finally:一般放在try…catch…的後面構造老是執行代碼塊,這就意味着程序不管正常執行仍是發生異常,這裏的代碼只要JVM不關閉都能執行,能夠將釋放外部資源的代碼寫在finally塊中。
- finalize:Object類中定義的方法,Java中容許使用finalize()方法在垃圾收集器將對象從內存中清除出去以前作必要的清理工做。這個方法是由垃圾收集器在銷燬對象時調用的,經過重寫finalize()方法能夠整理系統資源或者執行其餘清理工做。

 

啓動一個線程是調用run()仍是start()方法?

 啓動一個線程是調用start()方法,使線程所表明的虛擬處理機處於可運行狀態,這意味着它能夠由JVM 調度並執行,這並不意味着線程就會當即運行。run()方法是線程啓動後要進行回調(callback)的方法。

 

簡述synchronized 和java.util.concurrent.locks.Lock的異同

Lock是Java 5之後引入的新的API,和關鍵字synchronized相比

主要相同點:Lock 能完成synchronized所實現的全部功能;

主要不一樣點:Lock有比synchronized更精確的線程語義和更好的性能,並且不強制性的要求必定要得到鎖。synchronized會自動釋放鎖,而Lock必定要求程序員手工釋放,而且最好在finally 塊中釋放(這是釋放外部資源的最好的地方)

 

mysql存儲引擎的 InnoDB 與 MyISAM區別 

1)InnoDB支持事務,MyISAM不支持,這一點是很是之重要。事務是一種高級的處理方式,如在一些列增刪改中只要哪一個出錯還能夠回滾還原,而MyISAM就不能夠了。
 
2)MyISAM適合查詢以及插入爲主的應用,InnoDB適合頻繁修改以及涉及到安全性較高的應用
 
3)InnoDB支持外鍵,MyISAM不支持
 
4)從MySQL5.5.5之後,InnoDB是默認引擎
 
5) Innodb不支持全文索引,而MyISAM支持全文索引,查詢效率上MyISAM要高
 
6)InnoDB中不保存表的行數,如select count() from table時,InnoDB須要掃描一遍整個表來計算有多少行,可是MyISAM只要簡單的讀出保存好的行數便可。注意的是,當count()語句包含where條件時MyISAM也須要掃描整個表
 
7)對於自增加的字段,InnoDB中必須包含只有該字段的索引,可是在MyISAM表中能夠和其餘字段一塊兒創建聯合索引
 
8)清空整個表時,InnoDB是一行一行的刪除,效率很是慢。MyISAM則會重建表
 
9) 鎖機制不一樣: InnoDB 爲行級鎖,MyISAM 爲表級鎖
注意:當數據庫沒法肯定,所找的行時,也會變爲鎖定整個表。 
如: update table set num = 10 where username like 「%test%」; 

 

 

Spring MVC 運行流程

 

 
1.用戶發送請求到DispatchServlet
 
2.DispatchServlet根據請求路徑查詢具體的Handler
 
3.HandlerMapping返回一個HandlerExcutionChain給DispatchServlet
 
HandlerExcutionChain:Handler和Interceptor集合
 
4.DispatchServlet調用HandlerAdapter適配器
 
5.HandlerAdapter調用具體的Handler處理業務
 
6.Handler處理結束返回一個具體的ModelAndView給適配器
 
ModelAndView:model–>數據模型,view–>視圖名稱
 
7.適配器將ModelAndView給DispatchServlet
 
8.DispatchServlet把視圖名稱給ViewResolver視圖解析器
 
9.ViewResolver返回一個具體的視圖給DispatchServlet
 
10.渲染視圖
 
11.展現給用戶
 

 Redis所支持的數據結構

String(字符串)、List(列表)、Set(集合)、Zset(有序集合)、Hash(哈希)

 

Nginx實現負載均衡的方法有哪些

輪詢(默認)——每一個請求按時間順序逐一分配到不一樣的後端服務器,若是後端服務器down掉,能自動剔除。

weight ——指定輪詢概率,weight和訪問比率成正比,用於後端服務器性能不均的狀況。

ip_hash ——每一個請求按訪問ip的hash結果分配,這樣每一個訪客固定訪問一個後端服務器。

backup——其它全部的非backup機器down或者忙的時候,請求backup機器。因此這臺機器壓力會最輕。

down——表示單前的server暫時不參與負載

fair(第三方)按後端服務器的響應時間來分配請求,響應時間短的優先分配。與weight分配策略相似。

HashMap、HashTable、ConcurrentHashMap的區別

 

HashTable

 

  • 底層數組+鏈表實現,不管key仍是value都不能爲null,線程安全,實現線程安全的方式是在修改數據時鎖住整個HashTable,效率低,ConcurrentHashMap作了相關優化
  • 初始size爲11,擴容:newsize = olesize*2+1
  • 計算index的方法:index = (hash & 0x7FFFFFFF) % tab.length

HashMap

  • 底層數組+鏈表實現,可以存儲null鍵和null值,線程不安全
  • 初始size爲16,擴容:newsize = oldsize*2,size必定爲2的n次冪
  • 擴容針對整個Map,每次擴容時,原來數組中的元素依次從新計算存放位置,並從新插入
  • 插入元素後才判斷該不應擴容,有可能無效擴容(插入後若是擴容,若是沒有再次插入,就會產生無效擴容)
  • 當Map中元素總數超過Entry數組的75%,觸發擴容操做,爲了減小鏈表長度,元素分配更均勻
  • 計算index方法:index = hash & (tab.length – 1)

 

HashMap的初始值還要考慮加載因子:

  •  哈希衝突:若干Key的哈希值按數組大小取模後,若是落在同一個數組下標上,將組成一條Entry鏈,對Key的查找須要遍歷Entry鏈上的每一個元素執行equals()比較。
  • 加載因子:爲了下降哈希衝突的機率,默認當HashMap中的鍵值對達到數組大小的75%時,即會觸發擴容。所以,若是預估容量是100,即須要設定100/0.75=134的數組大小。
  • 空間換時間:若是但願加快Key查找的時間,還能夠進一步下降加載因子,加大初始大小,以下降哈希衝突的機率。

HashMap和Hashtable都是用hash算法來決定其元素的存儲,所以HashMap和Hashtable的hash表包含以下屬性:

  • 容量(capacity):hash表中桶的數量
  • 初始化容量(initial capacity):建立hash表時桶的數量,HashMap容許在構造器中指定初始化容量
  • 尺寸(size):當前hash表中記錄的數量
  • 負載因子(load factor):負載因子等於「size/capacity」。負載因子爲0,表示空的hash表,0.5表示半滿的散列表,依此類推。輕負載的散列表具備衝突少、適宜插入與查詢的特色(可是使用Iterator迭代元素時比較慢)

除此以外,hash表裏還有一個「負載極限」,「負載極限」是一個0~1的數值,「負載極限」決定了hash表的最大填滿程度。當hash表中的負載因子達到指定的「負載極限」時,hash表會自動成倍地增長容量(桶的數量),並將原有的對象從新分配,放入新的桶內,這稱爲rehashing。

HashMap和Hashtable的構造器容許指定一個負載極限,HashMap和Hashtable默認的「負載極限」爲0.75,這代表當該hash表的3/4已經被填滿時,hash表會發生rehashing。

「負載極限」的默認值(0.75)是時間和空間成本上的一種折中:

  • 較高的「負載極限」能夠下降hash表所佔用的內存空間,但會增長查詢數據的時間開銷,而查詢是最頻繁的操做(HashMap的get()與put()方法都要用到查詢)
  • 較低的「負載極限」會提升查詢數據的性能,但會增長hash表所佔用的內存開銷

程序猿能夠根據實際狀況來調整「負載極限」值。

ConcurrentHashMap

  • 底層採用分段的數組+鏈表實現,線程安全
  • 經過把整個Map分爲N個Segment,能夠提供相同的線程安全,可是效率提高N倍,默認提高16倍。(讀操做不加鎖,因爲HashEntry的value變量是 volatile的,也能保證讀取到最新的值。)
  • Hashtable的synchronized是針對整張Hash表的,即每次鎖住整張表讓線程獨佔,ConcurrentHashMap容許多個修改操做併發進行,其關鍵在於使用了鎖分離技術
  • 有些方法須要跨段,好比size()和containsValue(),它們可能須要鎖定整個表而而不只僅是某個段,這須要按順序鎖定全部段,操做完畢後,又按順序釋放全部段的鎖
  • 擴容:段內擴容(段內元素超過該段對應Entry數組長度的75%觸發擴容,不會對整個Map進行擴容),插入前檢測需不須要擴容,有效避免無效擴容

 

Lock和synchronized的區別

Lock是一個接口,而synchronized是Java中的關鍵字,synchronized是內置的語言實現;

synchronized在發生異常時,會自動釋放線程佔有的鎖,所以不會致使死鎖現象發生;而Lock在發生異常時,若是沒有主動經過unLock()去釋放鎖,則極可能形成死鎖現象,所以使用Lock時須要在finally塊中釋放鎖;

Lock可讓等待鎖的線程響應中斷,而synchronized卻不行,使用synchronized時,等待的線程會一直等待下去,不可以響應中斷;

經過Lock能夠知道有沒有成功獲取鎖,而synchronized卻沒法辦到。

Lock能夠提升多個線程進行讀操做的效率。

 ThreadLocal的原理做用

 

併發編程之ThreadLocal、Volatile、Synchronized、Atomic關鍵字比較 

相關文章
相關標籤/搜索