Java面試知識(shí)點(diǎn)

1.JVM 堆內(nèi)存和非堆內(nèi)存

  • 堆和非堆內(nèi)存
    按照官方的說法:“Java 虛擬機(jī)具有一個(gè)堆(Heap),堆是運(yùn)行時(shí)數(shù)據(jù)區(qū)域,所有類實(shí)例和數(shù)組的內(nèi)存均從此處分配。堆是在 Java 虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建的?!薄霸贘VM中堆之外的內(nèi)存稱為非堆內(nèi)存(Non-heap memory)”。
    JVM主要管理兩種類型的內(nèi)存:堆和非堆。
    Heap memory Code Cache
    Eden Space
    Survivor Space
    Tenured Gen
    non-heap memory Perm Gen
    native heap?(I guess)

  • 堆內(nèi)存
    Java 虛擬機(jī)具有一個(gè)堆,堆是運(yùn)行時(shí)數(shù)據(jù)區(qū)域,所有類實(shí)例和數(shù)組的內(nèi)存均從此處分配。堆是在 Java 虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建的。對(duì)象的堆內(nèi)存由稱為垃圾回收器的自動(dòng)內(nèi)存管理系統(tǒng)回收。
    堆的大小可以固定,也可以擴(kuò)大和縮小。堆的內(nèi)存不需要是連續(xù)空間。

  • 非堆內(nèi)存
    Java 虛擬機(jī)管理堆之外的內(nèi)存(稱為非堆內(nèi)存)。
    Java 虛擬機(jī)具有一個(gè)由所有線程共享的方法區(qū)。方法區(qū)屬于非堆內(nèi)存。它存儲(chǔ)每個(gè)類結(jié)構(gòu),如運(yùn)行時(shí)常數(shù)池、字段和方法數(shù)據(jù),以及方法和構(gòu)造方法的代碼。它是在 Java 虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建的。
    方法區(qū)在邏輯上屬于堆,但 Java 虛擬機(jī)實(shí)現(xiàn)可以選擇不對(duì)其進(jìn)行回收或壓縮。與堆類似,方法區(qū)的大小可以固定,也可以擴(kuò)大和縮小。方法區(qū)的內(nèi)存不需要是連續(xù)空間。
    除了方法區(qū)外,Java 虛擬機(jī)實(shí)現(xiàn)可能需要用于內(nèi)部處理或優(yōu)化的內(nèi)存,這種內(nèi)存也是非堆內(nèi)存。例如,JIT 編譯器需要內(nèi)存來存儲(chǔ)從 Java 虛擬機(jī)代碼轉(zhuǎn)換而來的本機(jī)代碼,從而獲得高性能。

  • 幾個(gè)基本概念
    PermGen space:全稱是Permanent Generation space,即永久代。就是說是永久保存的區(qū)域,用于存放Class和Meta信息,Class在被Load的時(shí)候被放入該區(qū)域,GC(Garbage Collection)應(yīng)該不會(huì)對(duì)PermGen space進(jìn)行清理,所以如果你的APP會(huì)LOAD很多CLASS的話,就很可能出現(xiàn)PermGen space錯(cuò)誤。
    Heap space:存放Instance。
    Java Heap分為3個(gè)區(qū),Young即新生代,Old即老生代和Permanent。
    Young保存剛實(shí)例化的對(duì)象。當(dāng)該區(qū)被填滿時(shí),GC會(huì)將對(duì)象移到Old區(qū)。Permanent區(qū)則負(fù)責(zé)保存反射對(duì)象。

  • 堆內(nèi)存分配
    JVM初始分配的堆內(nèi)存由-Xms指定,默認(rèn)是物理內(nèi)存的1/64;
    JVM最大分配的堆內(nèi)存由-Xmx指定,默認(rèn)是物理內(nèi)存的1/4。
    默認(rèn)空余堆內(nèi)存小于40%時(shí),JVM就會(huì)增大堆直到-Xmx的最大限制;
    空余堆內(nèi)存大于70%時(shí),JVM會(huì)減少堆直到-Xms的最小限制。
    因此服務(wù)器一般設(shè)置-Xms、-Xmx 相等以避免在每次GC 后調(diào)整堆的大小。
    說明:如果-Xmx 不指定或者指定偏小,應(yīng)用可能會(huì)導(dǎo)致java.lang.OutOfMemory錯(cuò)誤,此錯(cuò)誤來自JVM,不是Throwable的,無法用try…catch捕捉。

  • 非堆內(nèi)存分配

  1. JVM使用-XX:PermSize設(shè)置非堆內(nèi)存初始值,默認(rèn)是物理內(nèi)存的1/64;
  2. 由XX:MaxPermSize設(shè)置最大非堆內(nèi)存的大小,默認(rèn)是物理內(nèi)存的1/4。
    還有一說:MaxPermSize缺省值和-server -client選項(xiàng)相關(guān),-server選項(xiàng)下默認(rèn)MaxPermSize為64m,-client選項(xiàng)下默認(rèn)MaxPermSize為32m。這個(gè)我沒有實(shí)驗(yàn)。
  3. XX:MaxPermSize設(shè)置過小會(huì)導(dǎo)致java.lang.OutOfMemoryError: PermGen space 就是內(nèi)存益出。
  4. 為什么會(huì)內(nèi)存益出:
    這一部分內(nèi)存用于存放Class和Meta的信息,Class在被 Load的時(shí)候被放入PermGen space區(qū)域,它和存放Instance的Heap區(qū)域不同。
    GC(Garbage Collection)不會(huì)在主程序運(yùn)行期對(duì)PermGen space進(jìn)行清理,所以如果你的APP會(huì)LOAD很多CLASS 的話,就很可能出現(xiàn)PermGen space錯(cuò)誤。
  5. 這種錯(cuò)誤常見在web服務(wù)器對(duì)JSP進(jìn)行pre compile的時(shí)候。

2.MySQL大數(shù)據(jù)量分頁查詢方法及其優(yōu)化

---方法1: 直接使用數(shù)據(jù)庫提供的SQL語句
---語句樣式: MySQL中,可用如下方法: SELECT * FROM 表名稱 LIMIT M,N
---適應(yīng)場景: 適用于數(shù)據(jù)量較少的情況(元組百/千級(jí))
---原因/缺點(diǎn): 全表掃描,速度會(huì)很慢 且 有的數(shù)據(jù)庫結(jié)果集返回不穩(wěn)定(如某次返回1,2,3,另外的一次返回2,1,3). Limit限制的是從結(jié)果集的M位置處取出N條輸出,其余拋棄.
---方法2: 建立主鍵或唯一索引, 利用索引(假設(shè)每頁10條)**
---語句樣式: MySQL中,可用如下方法: SELECT * FROM 表名稱 WHERE id_pk > (pageNum10) LIMIT M
---適應(yīng)場景: 適用于數(shù)據(jù)量多的情況(元組數(shù)上萬)
---原因: 索引掃描,速度會(huì)很快. 有朋友提出: 因?yàn)閿?shù)據(jù)查詢出來并不是按照pk_id排序的,所以會(huì)有漏掉數(shù)據(jù)的情況,只能方法3
---方法3: 基于索引再排序
---語句樣式: MySQL中,可用如下方法: SELECT * FROM 表名稱 WHERE id_pk > (pageNum
10) ORDER BY id_pk ASC LIMIT M
---適應(yīng)場景: 適用于數(shù)據(jù)量多的情況(元組數(shù)上萬). 最好ORDER BY后的列對(duì)象是主鍵或唯一所以,使得ORDERBY操作能利用索引被消除但結(jié)果集是穩(wěn)定的(穩(wěn)定的含義,參見方法1)
---原因: 索引掃描,速度會(huì)很快. 但MySQL的排序操作,只有ASC沒有DESC(DESC是假的,未來會(huì)做真正的DESC,期待...).
---方法4: 基于索引使用prepare(第一個(gè)問號(hào)表示pageNum,第二個(gè)?表示每頁元組數(shù))**
---語句樣式: MySQL中,可用如下方法: PREPARE stmt_name FROM SELECT * FROM 表名稱 WHERE id_pk > (?* ?) ORDER BY id_pk ASC LIMIT M
---適應(yīng)場景: 大數(shù)據(jù)
---原因: 索引掃描,速度會(huì)很快. prepare語句又比一般的查詢語句快一點(diǎn)。

3.ThreadGroup

當(dāng)創(chuàng)建了好幾個(gè)線程的時(shí)候,很多線程的工作任務(wù)是類似或者一致的,這樣我們就可以使用ThreadGroup來管理他們,ThreadGroup可以隨時(shí)的獲取在他里面的線程的運(yùn)行狀態(tài),信息,或者一條命令關(guān)閉掉這個(gè)group里面的所有線程。

4.SpringMVC與Struts2的區(qū)別及執(zhí)行流程

Struts2是一個(gè)基于MVC設(shè)計(jì)模式的Web應(yīng)用框架,它本質(zhì)上相當(dāng)于一個(gè)servlet,在MVC設(shè)計(jì)模式中,Struts2作為控制器(Controller)來建立模型與視圖的數(shù)據(jù)交互 Struts2=struts1+webwork。
struts2的執(zhí)行流程:
1、客戶端瀏覽器發(fā)出HTTP請求。
2、根據(jù)web.xml配置,該請求被FilterDispatcher接收。
3、根據(jù)struts.xml配置,找到需要調(diào)用的Action類和方法, 并通過IoC方式,將值注入給Aciton。
4、Action調(diào)用業(yè)務(wù)邏輯組件處理業(yè)務(wù)邏輯,這一步包含表單驗(yàn)證。
5、Action執(zhí)行完畢,根據(jù)struts.xml中的配置找到對(duì)應(yīng)的返回結(jié)果result,并跳轉(zhuǎn)到相應(yīng)頁面。
6、返回HTTP響應(yīng)到客戶端瀏覽器。
springmvc全稱是spring web mvc,是spring框架一部分,是一個(gè)mvc的框架,和struts2一樣是一個(gè)表現(xiàn)層框架。
springMVC的執(zhí)行流程:
1、 用戶發(fā)送請求至前端控制器DispatcherServlet
2、 DispatcherServlet收到請求調(diào)用HandlerMapping處理器映射器查找Handler。
3、 處理器映射器根據(jù)請求url找到具體的處理器,生成處理器對(duì)象及處理器攔截器(如果有則生成)一并返回給DispatcherServlet。
4、 DispatcherServlet通過HandlerAdapter處理器適配器調(diào)用處理器
5、 HandlerAdapter調(diào)用處理器Handler
6、 Handler執(zhí)行完成返回ModelAndView
7、 HandlerAdapter將Handler執(zhí)行結(jié)果ModelAndView返回給DispatcherServlet
8、 DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器,ViewReslover根據(jù)邏輯視圖名解析View
9、 ViewReslover返回View
10、 DispatcherServlet對(duì)View進(jìn)行渲染視圖(即將模型數(shù)據(jù)填充至request域)。
11、 DispatcherServlet響應(yīng)用戶

Springmvc與struts2的本質(zhì)區(qū)別
1、springmvc入口是一個(gè)servlet前端控制器,struts2入口是一個(gè)filter過濾器。
2、struts2通過在action類中定義成員變量接收請求參數(shù),struts2只能使用多例模式管理action。
springmvc通過在controller方法中定義形參接收請求參數(shù),springmvc可以使用單例模式管理controller。
3、springmvc是基于方法開發(fā)的,注解開發(fā)中使用requestMapping將url和方法進(jìn)行映射,如果根據(jù)url找到controller類的方法生成一個(gè)Handler處理器對(duì)象(只包括一個(gè)method)。
struts2是基于類開發(fā),每個(gè)請求過來創(chuàng)建一個(gè)action實(shí)例,實(shí)例對(duì)象中有若干的方法。
開發(fā)中建議使用springmvc,springmvc方法更類似service業(yè)務(wù)方法。
4、Struts采用值棧存儲(chǔ)請求和響應(yīng)的數(shù)據(jù),通過OGNL存取數(shù)據(jù), springmvc通過參數(shù)綁定器是將request請求內(nèi)容解析,并給方法形參賦值。
5、struts2和springmvc的速度是相當(dāng)?shù)?,由于struts2的漏洞較多,很多企業(yè)轉(zhuǎn)向使用springmvc了。

5.談?wù)勀銓?duì)Struts的理解。

  1. struts是一個(gè)按MVC模式設(shè)計(jì)的Web層框架,其實(shí)它就是一個(gè)大大的servlet,這個(gè)Servlet名為ActionServlet,或是ActionServlet的子類。我們可以在web.xml文件中將符合某種特征的所有請求交給這個(gè)Servlet處理,這個(gè)Servlet再參照一個(gè)配置文件(通常為/WEB-INF/struts-config.xml)將各個(gè)請求分別分配給不同的action去處理。
    一個(gè)擴(kuò)展知識(shí)點(diǎn):struts的配置文件可以有多個(gè),可以按模塊配置各自的配置文件,這樣可以防止配置文件的過度膨脹;
    2.ActionServlet把請求交給action去處理之前,會(huì)將請求參數(shù)封裝成一個(gè)formbean對(duì)象(就是一個(gè)java類,這個(gè)類中的每個(gè)屬性對(duì)應(yīng)一個(gè)請求參數(shù)),封裝成一個(gè)什么樣的formbean對(duì)象呢?看配置文件。
    3.要說明的是, ActionServlet把formbean對(duì)象傳遞給action的execute方法之前,可能會(huì)調(diào)用formbean的validate方法進(jìn)行校驗(yàn),只有校驗(yàn)通過后才將這個(gè)formbean對(duì)象傳遞給action的execute方法,否則,它將返回一個(gè)錯(cuò)誤頁面,這個(gè)錯(cuò)誤頁面由input屬性指定,(看配置文件)作者為什么將這里命名為input屬性,而不是error屬性,我們后面結(jié)合實(shí)際的運(yùn)行效果進(jìn)行分析。
    4.action執(zhí)行完后要返回顯示的結(jié)果視圖,這個(gè)結(jié)果視圖是用一個(gè)ActionForward對(duì)象來表示的,actionforward對(duì)象通過struts-config.xml配置文件中的配置關(guān)聯(lián)到某個(gè)jsp頁面,因?yàn)槌绦蛑惺褂玫氖窃趕truts-config.xml配置文件為jsp頁面設(shè)置的邏輯名,這樣可以實(shí)現(xiàn)action程序代碼與返回的jsp頁面名稱的解耦。

6.談?wù)勀銓?duì)Hibernate的理解。

1.面向?qū)ο笤O(shè)計(jì)的軟件內(nèi)部運(yùn)行過程可以理解成就是在不斷創(chuàng)建各種新對(duì)象、建立對(duì)象之間的關(guān)系,調(diào)用對(duì)象的方法來改變各個(gè)對(duì)象的狀態(tài)和對(duì)象消亡的過程,不管程序運(yùn)行的過程和操作怎么樣,本質(zhì)上都是要得到一個(gè)結(jié)果,程序上一個(gè)時(shí)刻和下一個(gè)時(shí)刻的運(yùn)行結(jié)果的差異就表現(xiàn)在內(nèi)存中的對(duì)象狀態(tài)發(fā)生了變化。
2.為了在關(guān)機(jī)和內(nèi)存空間不夠的狀況下,保持程序的運(yùn)行狀態(tài),需要將內(nèi)存中的對(duì)象狀態(tài)保存到持久化設(shè)備和從持久化設(shè)備中恢復(fù)出對(duì)象的狀態(tài),通常都是保存到關(guān)系數(shù)據(jù)庫來保存大量對(duì)象信息。從Java程序的運(yùn)行功能上來講,保存對(duì)象狀態(tài)的功能相比系統(tǒng)運(yùn)行的其他功能來說,應(yīng)該是一個(gè)很不起眼的附屬功能,java采用jdbc來實(shí)現(xiàn)這個(gè)功能,這個(gè)不起眼的功能卻要編寫大量的代碼,而做的事情僅僅是保存對(duì)象和恢復(fù)對(duì)象,并且那些大量的jdbc代碼并沒有什么技術(shù)含量,基本上是采用一套例行公事的標(biāo)準(zhǔn)代碼模板來編寫,是一種苦活和重復(fù)性的工作。
3.通過數(shù)據(jù)庫保存java程序運(yùn)行時(shí)產(chǎn)生的對(duì)象和恢復(fù)對(duì)象,其實(shí)就是實(shí)現(xiàn)了java對(duì)象與關(guān)系數(shù)據(jù)庫記錄的映射關(guān)系,稱為ORM(即Object Relation Mapping),人們可以通過封裝JDBC代碼來實(shí)現(xiàn)了這種功能,封裝出來的產(chǎn)品稱之為ORM框架,Hibernate就是其中的一種流行ORM框架。使用Hibernate框架,不用寫JDBC代碼,僅僅是調(diào)用一個(gè)save方法,就可以將對(duì)象保存到關(guān)系數(shù)據(jù)庫中,僅僅是調(diào)用一個(gè)get方法,就可以從數(shù)據(jù)庫中加載出一個(gè)對(duì)象。
4.使用Hibernate的基本流程是:配置Configuration對(duì)象、產(chǎn)生SessionFactory、創(chuàng)建session對(duì)象,啟動(dòng)事務(wù),完成CRUD操作,提交事務(wù),關(guān)閉session。
5.使用Hibernate時(shí),先要配置hibernate.cfg.xml文件,其中配置數(shù)據(jù)庫連接信息和方言等,還要為每個(gè)實(shí)體配置相應(yīng)的hbm.xml文件,hibernate.cfg.xml文件中需要登記每個(gè)hbm.xml文件。
6.在應(yīng)用Hibernate時(shí),重點(diǎn)要了解Session的緩存原理,級(jí)聯(lián),延遲加載和hql查詢。

7.Sprig AOP

前段時(shí)間寫的java設(shè)計(jì)模式--代理模式,最近在看Spring Aop的時(shí)候,覺得于代理模式應(yīng)該有密切的聯(lián)系,于是決定了解下Spring Aop的實(shí)現(xiàn)原理。
說起AOP就不得不說下OOP了,OOP中引入封裝、繼承和多態(tài)性等概念來建立一種對(duì)象層次結(jié)構(gòu),用以模擬公共行為的一個(gè)集合。但是,如果我們需要為部分對(duì)象引入公共部分的時(shí)候,OOP就會(huì)引入大量重復(fù)的代碼。例如:日志功能。
AOP技術(shù)利用一種稱為“橫切”的技術(shù),解剖封裝的對(duì)象內(nèi)部,并將那些影響了多個(gè)類的公共行為封裝到一個(gè)可重用模塊,這樣就能減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于未來的可操作性和可維護(hù)性。AOP把軟件系統(tǒng)分為兩個(gè)部分:核心關(guān)注點(diǎn)和橫切關(guān)注點(diǎn)。業(yè)務(wù)處理的主要流程是核心關(guān)注點(diǎn),與之關(guān)系不大的部分是橫切關(guān)注點(diǎn)。橫切關(guān)注點(diǎn)的一個(gè)特點(diǎn)是,他們經(jīng)常發(fā)生在核心關(guān)注點(diǎn)的多處,而各處都基本相似。比如權(quán)限認(rèn)證、日志、事務(wù)處理。

實(shí)現(xiàn)AOP的技術(shù),主要分為兩大類:
一是采用動(dòng)態(tài)代理技術(shù),利用截取消息的方式,對(duì)該消息進(jìn)行裝飾,以取代原有對(duì)象行為的執(zhí)行;
二是采用靜態(tài)織入的方式,引入特定的語法創(chuàng)建“方面”,從而使得編譯器可以在編譯期間織入有關(guān)“方面”的代碼。
Spring AOP 的實(shí)現(xiàn)原理其實(shí)很簡單:AOP 框架負(fù)責(zé)動(dòng)態(tài)地生成 AOP 代理類,這個(gè)代理類的方法則由 Advice 和回調(diào)目標(biāo)對(duì)象的方法所組成,并將該對(duì)象可作為目標(biāo)對(duì)象使用。AOP 代理包含了目標(biāo)對(duì)象的全部方法,但 AOP 代理中的方法與目標(biāo)對(duì)象的方法存在差異,AOP 方法在特定切入點(diǎn)添加了增強(qiáng)處理,并回調(diào)了目標(biāo)對(duì)象的方法。

Spring AOP使用動(dòng)態(tài)代理技術(shù)在運(yùn)行期織入增強(qiáng)代碼。使用兩種代理機(jī)制:

基于JDK的動(dòng)態(tài)代理(JDK本身只提供接口的代理);
基于CGlib的動(dòng)態(tài)代理。
1)JDK的動(dòng)態(tài)代理主要涉及java.lang.reflect包中的兩個(gè)類:Proxy和InvocationHandler。其中InvocationHandler只是一個(gè)接口,可以通過實(shí)現(xiàn)該接口定義橫切邏輯,并通過反射機(jī)制調(diào)用目標(biāo)類的代碼,動(dòng)態(tài)的將橫切邏輯與業(yè)務(wù)邏輯織在一起。而Proxy利用InvocationHandler動(dòng)態(tài)創(chuàng)建一個(gè)符合某一接口的實(shí)例,生成目標(biāo)類的代理對(duì)象。 其代理對(duì)象必須是某個(gè)接口的實(shí)現(xiàn),它是通過在運(yùn)行期間創(chuàng)建一個(gè)接口的實(shí)現(xiàn)類來完成對(duì)目標(biāo)對(duì)象的代理.只能實(shí)現(xiàn)接口的類生成代理,而不能針對(duì)類
2)CGLib采用底層的字節(jié)碼技術(shù),為一個(gè)類創(chuàng)建子類,并在子類中采用方法攔截的技術(shù)攔截所有父類的調(diào)用方法,并順勢織入橫切邏輯.它運(yùn)行期間生成的代理對(duì)象是目標(biāo)類的擴(kuò)展子類.所以無法通知final的方法,因?yàn)樗鼈儾荒鼙桓矊?是針對(duì)類實(shí)現(xiàn)代理,主要是為指定的類生成一個(gè)子類,覆蓋其中方法.
在spring中默認(rèn)情況下使用JDK動(dòng)態(tài)代理實(shí)現(xiàn)AOP,如果proxy-target-class設(shè)置為true或者使用了優(yōu)化策略那么會(huì)使用CGLIB來創(chuàng)建動(dòng)態(tài)代理.Spring AOP在這兩種方式的實(shí)現(xiàn)上基本一樣.以JDK代理為例,會(huì)使用JdkDynamicAopProxy來創(chuàng)建代理,在invoke()方法首先需要織入到當(dāng)前類的增強(qiáng)器封裝到攔截器鏈中,然后遞歸的調(diào)用這些攔截器完成功能的織入.最終返回代理對(duì)象.

8.介紹一下Hibernate的二級(jí)緩存

(1)緩存就是把以前從數(shù)據(jù)庫中查詢出來和使用過的對(duì)象保存在內(nèi)存中(一個(gè)數(shù)據(jù)結(jié)構(gòu)中),這個(gè)數(shù)據(jù)結(jié)構(gòu)通常是或類似Hashmap,當(dāng)以后要使用某個(gè)對(duì)象時(shí),先查詢緩存中是否有這個(gè)對(duì)象,如果有則使用緩存中的對(duì)象,如果沒有則去查詢數(shù)據(jù)庫,并將查詢出來的對(duì)象保存在緩存中,以便下次使用。
(2)Hibernate的Session就是一種緩存,我們通常將之稱為Hibernate的一級(jí)緩存,當(dāng)想使用session從數(shù)據(jù)庫中查詢出一個(gè)對(duì)象時(shí),Session也是先從自己內(nèi)部查看是否存在這個(gè)對(duì)象,存在則直接返回,不存在才去訪問數(shù)據(jù)庫,并將查詢的結(jié)果保存在自己內(nèi)部。由于Session代表一次會(huì)話過程,一個(gè)Session與一個(gè)數(shù)據(jù)庫連接相關(guān)連,所以Session最好不要長時(shí)間保持打開,通常僅用于一個(gè)事務(wù)當(dāng)中,在事務(wù)結(jié)束時(shí)就應(yīng)關(guān)閉。并且Session是線程不安全的,被多個(gè)線程共享時(shí)容易出現(xiàn)問題。通常只有那種全局意義上的緩存才是真正的緩存應(yīng)用,才有較大的緩存價(jià)值,因此,Hibernate的Session這一級(jí)緩存的緩存作用并不明顯,應(yīng)用價(jià)值不大。Hibernate的二級(jí)緩存就是要為Hibernate配置一種全局緩存,讓多個(gè)線程和多個(gè)事務(wù)都可以共享這個(gè)緩存。我們希望的是一個(gè)人使用過,其他人也可以使用,session沒有這種效果。
(3)二級(jí)緩存是獨(dú)立于Hibernate的軟件部件,屬于第三方的產(chǎn)品,多個(gè)廠商和組織都提供有緩存產(chǎn)品,例如,EHCache和OSCache等等。在Hibernate中使用二級(jí)緩存,首先就要在hibernate.cfg.xml配置文件中配置使用哪個(gè)廠家的緩存產(chǎn)品,接著需要配置該緩存產(chǎn)品自己的配置文件,最后要配置Hibernate中的哪些實(shí)體對(duì)象要納入到二級(jí)緩存的管理中。明白了二級(jí)緩存原理和有了這個(gè)思路后,很容易配置起Hibernate的二級(jí)緩存。擴(kuò)展知識(shí):一個(gè)SessionFactory可以關(guān)聯(lián)一個(gè)二級(jí)緩存,也即一個(gè)二級(jí)緩存只能負(fù)責(zé)緩存一個(gè)數(shù)據(jù)庫中的數(shù)據(jù),當(dāng)使用Hibernate 的二級(jí)緩存后,注意不要有其他的應(yīng)用或SessionFactory來更改當(dāng)前數(shù)據(jù)庫中的數(shù)據(jù),這樣緩存的數(shù)據(jù)就會(huì)與數(shù)據(jù)庫中的實(shí)際數(shù)據(jù)不一致。

9.三大框架各起的作用

struts 在SSH 框架中起控制的作用 , 其核心是(控制器)Controller, 即ActionServlet,而 ActionServlet 的核心就是Struts-config.xml. 主要控制邏輯關(guān)系的處理 . hibernate 是數(shù)據(jù)持久化層 , 是一種新的對(duì)象、關(guān)系的映射工具 , 提供了從 Java 類到數(shù)據(jù)表的映射,也提供了數(shù)據(jù)查詢和恢復(fù)等機(jī)制 , 大大減少數(shù)據(jù)訪問的復(fù)雜度。把對(duì)數(shù)據(jù)庫的直接操作 , 轉(zhuǎn)換為對(duì)持久對(duì)象的操作。
spring 是一個(gè)輕量級(jí)的控制反轉(zhuǎn) (IoC) 和面向切面 (AOP) 的容器框架, 面向接口的編程 , 由容器控制程序之間的(依賴)關(guān)系,而非傳統(tǒng)實(shí)現(xiàn)中,由程序代碼直接操控。這也就是所謂“ 控制反轉(zhuǎn)” 的概念所在:(依賴)控制權(quán)由應(yīng)用代碼中轉(zhuǎn)到了外部容器,控制權(quán)的轉(zhuǎn)移,是所謂反轉(zhuǎn)。依賴注入,即組件之間的依賴關(guān)系由容器在運(yùn)行期決定,形象的來說,即由容器動(dòng)態(tài)的將某種依賴關(guān)系注入到組件之中 起到的主要作用是解耦。

10.spring核心:aop和ioc的解釋?隔離范圍? 3種注入方法?

(1)aop:Spring提供了對(duì)AOP技術(shù)的良好封裝, AOP稱為面向切面編程,就是系統(tǒng)中有很多各不相干的類的方法,在這些眾多方法中要加入某種系統(tǒng)功能的代碼;例如,加入日志,加入權(quán)限判斷,加入異常處理,這種應(yīng)用稱為AOP。實(shí)現(xiàn)AOP功能采用的是代理技術(shù),客戶端程序不再調(diào)用目標(biāo),而調(diào)用代理類,代理類與目標(biāo)類對(duì)外具有相同的方法聲明,有兩種方式可以實(shí)現(xiàn)相同的方法聲明,一是實(shí)現(xiàn)相同的接口,二是作為目標(biāo)的子類在,JDK中采用Proxy類產(chǎn)生動(dòng)態(tài)代理的方式為某個(gè)接口生成實(shí)現(xiàn)類,spring提供了這種支持,只需要在spring配置文件中配置這兩個(gè)元素即可實(shí)現(xiàn)代理和aop功能;
(2)Ioc:Spring提供了對(duì)IOC良好支持,IOC是一種編程思想,是一種架構(gòu)藝術(shù),利用這種思想可以很好地實(shí)現(xiàn)模塊之間的解耦。IOC也稱為DI(Depency Injection);IOC可以理解為‘面向接口編程思想’的一種實(shí)現(xiàn)方法,通過IOC實(shí)現(xiàn)了強(qiáng)制的‘面向接口編程’。
(3)隔離范圍:Spring支持JDBC規(guī)范定義的四種隔離級(jí)別
Default默認(rèn)的事務(wù)隔離級(jí)別
READ_UNCOMMITTED讀未提交,一個(gè)事務(wù)可以操作另外一個(gè)未提交的事務(wù),不能避免臟讀,不可重復(fù)讀,幻讀,隔離級(jí)別最低,并發(fā)性 能最高
READ_COMMITTED讀已提交,一個(gè)事務(wù)不可以操作另外一個(gè)未提交的事務(wù), 能防止臟讀,不能避免不可重復(fù)讀,幻讀。
repeatable_read能夠避免臟讀,不可重復(fù)讀,不能避免幻讀
SERIALIZABLE隔離級(jí)別最高,消耗資源最低,代價(jià)最高,能夠防止臟讀, 不可重復(fù)讀,幻讀。
(4)Spring的注入和IoC反轉(zhuǎn)控制是一回事;關(guān)于getter和setter方式的注入;
Autowire=”defualt”;autowire=”byName”;autowire=”byType”;

11.Spring Bean的作用域之間有什么區(qū)別?

Spring容器中的bean可以分為5個(gè)范圍。所有范圍的名稱都是自說明的,但是為了避免混淆,還是讓我們來解釋一下:
singleton:這種bean范圍是默認(rèn)的,這種范圍確保不管接受到多少個(gè)請求,每個(gè)容器中只有一個(gè)bean的實(shí)例,單例的模式由bean factory自身來維護(hù)。
prototype:原形范圍與單例范圍相反,為每一個(gè)bean請求提供一個(gè)實(shí)例。
request:在請求bean范圍內(nèi)會(huì)每一個(gè)來自客戶端的網(wǎng)絡(luò)請求創(chuàng)建一個(gè)實(shí)例,在請求完成以后,bean會(huì)失效并被垃圾回收器回收。
Session:與請求范圍類似,確保每個(gè)session中有一個(gè)bean的實(shí)例,在session過期后,bean會(huì)隨之失效。
global-session:global-session和Portlet應(yīng)用相關(guān)。當(dāng)你的應(yīng)用部署在Portlet容器中工作時(shí),它包含很多portlet。如果你想要聲明讓所有的portlet共用全局的存儲(chǔ)變量的話,那么這全局變量需要存儲(chǔ)在global-session中。

12.大型網(wǎng)站在架構(gòu)上應(yīng)當(dāng)考慮哪些問題?

1.分層:分層是處理任何復(fù)雜系統(tǒng)最常見的手段之一,將系統(tǒng)橫向切分成若干個(gè)層面,每個(gè)層面只承擔(dān)單一的職責(zé),然后通過下層為上層提供的基礎(chǔ)設(shè)施和服務(wù)以及上層對(duì)下層的調(diào)用來形成一個(gè)完整的復(fù)雜的系統(tǒng)。計(jì)算機(jī)網(wǎng)絡(luò)的開放系統(tǒng)互聯(lián)參考模型(OSI/RM)和Internet的TCP/IP模型都是分層結(jié)構(gòu),大型網(wǎng)站的軟件系統(tǒng)也可以使用分層的理念將其分為持久層(提供數(shù)據(jù)存儲(chǔ)和訪問服務(wù))、業(yè)務(wù)層(處理業(yè)務(wù)邏輯,系統(tǒng)中最核心的部分)和表示層(系統(tǒng)交互、視圖展示)。需要指出的是:(1)分層是邏輯上的劃分,在物理上可以位于同一設(shè)備上也可以在不同的設(shè)備上部署不同的功能模塊,這樣可以使用更多的計(jì)算資源來應(yīng)對(duì)用戶的并發(fā)訪問;(2)層與層之間應(yīng)當(dāng)有清晰的邊界,這樣分層才有意義,才更利于軟件的開發(fā)和維護(hù)。
2.分割:分割是對(duì)軟件的縱向切分。我們可以將大型網(wǎng)站的不同功能和服務(wù)分割開,形成高內(nèi)聚低耦合的功能模塊(單元)。在設(shè)計(jì)初期可以做一個(gè)粗粒度的分割,將網(wǎng)站分割為若干個(gè)功能模塊,后期還可以進(jìn)一步對(duì)每個(gè)模塊進(jìn)行細(xì)粒度的分割,這樣一方面有助于軟件的開發(fā)和維護(hù),另一方面有助于分布式的部署,提供網(wǎng)站的并發(fā)處理能力和功能的擴(kuò)展。
3.分布式:除了上面提到的內(nèi)容,網(wǎng)站的靜態(tài)資源(JavaScript、CSS、圖片等)也可以采用獨(dú)立分布式部署并采用獨(dú)立的域名,這樣可以減輕應(yīng)用服務(wù)器的負(fù)載壓力,也使得瀏覽器對(duì)資源的加載更快。數(shù)據(jù)的存取也應(yīng)該是分布式的,傳統(tǒng)的商業(yè)級(jí)關(guān)系型數(shù)據(jù)庫產(chǎn)品基本上都支持分布式部署,而新生的NoSQL產(chǎn)品幾乎都是分布式的。當(dāng)然,網(wǎng)站后臺(tái)的業(yè)務(wù)處理也要使用分布式技術(shù),例如查詢索引的構(gòu)建、數(shù)據(jù)分析等,這些業(yè)務(wù)計(jì)算規(guī)模龐大,可以使用Hadoop以及MapReduce分布式計(jì)算框架來處理。
4.集群:集群使得有更多的服務(wù)器提供相同的服務(wù),可以更好的提供對(duì)并發(fā)的支持。
5.緩存:所謂緩存就是用空間換取時(shí)間的技術(shù),將數(shù)據(jù)盡可能放在距離計(jì)算最近的位置。使用緩存是網(wǎng)站優(yōu)化的第一定律。我們通常說的CDN、反向代理、熱點(diǎn)數(shù)據(jù)都是對(duì)緩存技術(shù)的使用。
6.異步:異步是實(shí)現(xiàn)軟件實(shí)體之間解耦合的又一重要手段。異步架構(gòu)是典型的生產(chǎn)者消費(fèi)者模式,二者之間沒有直接的調(diào)用關(guān)系,只要保持?jǐn)?shù)據(jù)結(jié)構(gòu)不變,彼此功能實(shí)現(xiàn)可以隨意變化而不互相影響,這對(duì)網(wǎng)站的擴(kuò)展非常有利。使用異步處理還可以提高系統(tǒng)可用性,加快網(wǎng)站的響應(yīng)速度(用Ajax加載數(shù)據(jù)就是一種異步技術(shù)),同時(shí)還可以起到削峰作用(應(yīng)對(duì)瞬時(shí)高并發(fā))。"能推遲處理的都要推遲處理"是網(wǎng)站優(yōu)化的第二定律,而異步是踐行網(wǎng)站優(yōu)化第二定律的重要手段。
7.冗余:各種服務(wù)器都要提供相應(yīng)的冗余服務(wù)器以便在某臺(tái)或某些服務(wù)器宕機(jī)時(shí)還能保證網(wǎng)站可以正常工作,同時(shí)也提供了災(zāi)難恢復(fù)的可能性。冗余是網(wǎng)站高可用性的重要保證。

13.你用過的網(wǎng)站前端優(yōu)化的技術(shù)有哪些?

①瀏覽器訪問優(yōu)化:

  • 減少HTTP請求數(shù)量:合并CSS、合并javascript、合并圖片(CSS Sprite)
  • 使用瀏覽器緩存:通過設(shè)置HTTP響應(yīng)頭中的Cache-Control和Expires屬性,將CSS、JavaScript、圖片等在瀏覽器中緩存,當(dāng)這些靜態(tài)資源需要更新時(shí),可以更新HTML文件中的引用來讓瀏覽器重新請求新的資源
  • 啟用壓縮
  • CSS前置,JavaScript后置 -減少Cookie傳輸
    ② CDN加速:CDN(ContentDistribute Network)的本質(zhì)仍然是緩存,將數(shù)據(jù)緩存在離用戶最近的地方,CDN通常部署在網(wǎng)絡(luò)運(yùn)營商的機(jī)房,不僅可以提升響應(yīng)速度,還可以減少應(yīng)用服務(wù)器的壓力。當(dāng)然,CDN緩存的通常都是靜態(tài)資源。
    ③反向代理:反向代理相當(dāng)于應(yīng)用服務(wù)器的一個(gè)門面,可以保護(hù)網(wǎng)站的安全性,也可以實(shí)現(xiàn)負(fù)載均衡的功能,當(dāng)然最重要的是它緩存了用戶訪問的熱點(diǎn)資源,可以直接從反向代理將某些內(nèi)容返回給用戶瀏覽器。

14.你使用過的應(yīng)用服務(wù)器優(yōu)化技術(shù)有哪些?

①分布式緩存:緩存的本質(zhì)就是內(nèi)存中的哈希表,如果設(shè)計(jì)一個(gè)優(yōu)質(zhì)的哈希函數(shù),那么理論上哈希表讀寫的漸近時(shí)間復(fù)雜度為O(1)。緩存主要用來存放那些讀寫比很高、變化很少的數(shù)據(jù),這樣應(yīng)用程序讀取數(shù)據(jù)時(shí)先到緩存中讀取,如果沒有或者數(shù)據(jù)已經(jīng)失效再去訪問數(shù)據(jù)庫或文件系統(tǒng),并根據(jù)擬定的規(guī)則將數(shù)據(jù)寫入緩存。對(duì)網(wǎng)站數(shù)據(jù)的訪問也符合二八定律(Pareto分布,冪律分布),即80%的訪問都集中在20%的數(shù)據(jù)上,如果能夠?qū)⑦@20%的數(shù)據(jù)緩存起來,那么系統(tǒng)的性能將得到顯著的改善。當(dāng)然,使用緩存需要解決以下幾個(gè)問題:

  • 頻繁修改的數(shù)據(jù);
  • 數(shù)據(jù)不一致與臟讀;
  • 緩存雪崩(可以采用分布式緩存服務(wù)器集群加以解決,memcached是廣泛采用的解決方案);
  • 緩存預(yù)熱;
  • 緩存穿透(惡意持續(xù)請求不存在的數(shù)據(jù))。
    ②異步操作:可以使用消息隊(duì)列將調(diào)用異步化,通過異步處理將短時(shí)間高并發(fā)產(chǎn)生的事件消息存儲(chǔ)在消息隊(duì)列中,從而起到削峰作用。電商網(wǎng)站在進(jìn)行促銷活動(dòng)時(shí),可以將用戶的訂單請求存入消息隊(duì)列,這樣可以抵御大量的并發(fā)訂單請求對(duì)系統(tǒng)和數(shù)據(jù)庫的沖擊。目前,絕大多數(shù)的電商網(wǎng)站即便不進(jìn)行促銷活動(dòng),訂單系統(tǒng)都采用了消息隊(duì)列來處理。
    ③使用集群。
    ④代碼優(yōu)化:
    -多線程:基于Java的Web開發(fā)基本上都通過多線程的方式響應(yīng)用戶的并發(fā)請求,使用多線程技術(shù)在編程上要解決線程安全問題,主要可以考慮以下幾個(gè)方面:A. 將對(duì)象設(shè)計(jì)為無狀態(tài)對(duì)象(這和面向?qū)ο蟮木幊逃^點(diǎn)是矛盾的,在面向?qū)ο蟮氖澜缰斜灰暈椴涣荚O(shè)計(jì)),這樣就不會(huì)存在并發(fā)訪問時(shí)對(duì)象狀態(tài)不一致的問題。B. 在方法內(nèi)部創(chuàng)建對(duì)象,這樣對(duì)象由進(jìn)入方法的線程創(chuàng)建,不會(huì)出現(xiàn)多個(gè)線程訪問同一對(duì)象的問題。使用ThreadLocal將對(duì)象與線程綁定也是很好的做法,這一點(diǎn)在前面已經(jīng)探討過了。C. 對(duì)資源進(jìn)行并發(fā)訪問時(shí)應(yīng)當(dāng)使用合理的鎖機(jī)制。
  • 非阻塞I/O:使用單線程和非阻塞I/O是目前公認(rèn)的比多線程的方式更能充分發(fā)揮服務(wù)器性能的應(yīng)用模式,基于Node.js構(gòu)建的服務(wù)器就采用了這樣的方式。Java在JDK 1.4中就引入了NIO(Non-blockingI/O),在Servlet3規(guī)范中又引入了異步Servlet的概念,這些都為在服務(wù)器端采用非阻塞I/O提供了必要的基礎(chǔ)。
  • 資源復(fù)用:資源復(fù)用主要有兩種方式,一是單例,二是對(duì)象池,我們使用的數(shù)據(jù)庫連接池、線程池都是對(duì)象池化技術(shù),這是典型的用空間換取時(shí)間的策略,另一方面也實(shí)現(xiàn)對(duì)資源的復(fù)用,從而避免了不必要的創(chuàng)建和釋放資源所帶來的開銷。

15.Hibernate與Mybatis比較

第一方面:開發(fā)速度的對(duì)比
就開發(fā)速度而言,Hibernate的真正掌握要比Mybatis來得難些。Mybatis框架相對(duì)簡單很容易上手,但也相對(duì)簡陋些。個(gè)人覺得要用好Mybatis還是首先要先理解好Hibernate。
比起兩者的開發(fā)速度,不僅僅要考慮到兩者的特性及性能,更要根據(jù)項(xiàng)目需求去考慮究竟哪一個(gè)更適合項(xiàng)目開發(fā),比如:一個(gè)項(xiàng)目中用到的復(fù)雜查詢基本沒有,就是簡單的增刪改查,這樣選擇hibernate效率就很快了,因?yàn)榛镜膕ql語句已經(jīng)被封裝好了,根本不需要你去寫sql語句,這就節(jié)省了大量的時(shí)間,但是對(duì)于一個(gè)大型項(xiàng)目,復(fù)雜語句較多,這樣再去選擇hibernate就不是一個(gè)太好的選擇,選擇mybatis就會(huì)加快許多,而且語句的管理也比較方便。

第二方面:開發(fā)工作量的對(duì)比
Hibernate和MyBatis都有相應(yīng)的代碼生成工具??梢陨珊唵位镜腄AO層方法。針對(duì)高級(jí)查詢,Mybatis需要手動(dòng)編寫SQL語句,以及ResultMap。而Hibernate有良好的映射機(jī)制,開發(fā)者無需關(guān)心SQL的生成與結(jié)果映射,可以更專注于業(yè)務(wù)流程。

第三方面:sql優(yōu)化方面
Hibernate的查詢會(huì)將表中的所有字段查詢出來,這一點(diǎn)會(huì)有性能消耗。Hibernate也可以自己寫SQL來指定需要查詢的字段,但這樣就破壞了Hibernate開發(fā)的簡潔性。而Mybatis的SQL是手動(dòng)編寫的,所以可以按需求指定查詢的字段。
Hibernate HQL語句的調(diào)優(yōu)需要將SQL打印出來,而Hibernate的SQL被很多人嫌棄因?yàn)樘罅?。MyBatis的SQL是自己手動(dòng)寫的所以調(diào)整方便。但Hibernate具有自己的日志統(tǒng)計(jì)。Mybatis本身不帶日志統(tǒng)計(jì),使用Log4j進(jìn)行日志記錄。

第四方面:對(duì)象管理的對(duì)比
Hibernate 是完整的對(duì)象/關(guān)系映射解決方案,它提供了對(duì)象狀態(tài)管理(state management)的功能,使開發(fā)者不再需要理會(huì)底層數(shù)據(jù)庫系統(tǒng)的細(xì)節(jié)。也就是說,相對(duì)于常見的 JDBC/SQL 持久層方案中需要管理 SQL 語句,Hibernate采用了更自然的面向?qū)ο蟮囊暯莵沓志没?Java 應(yīng)用中的數(shù)據(jù)。
換句話說,使用 Hibernate 的開發(fā)者應(yīng)該總是關(guān)注對(duì)象的狀態(tài)(state),不必考慮 SQL 語句的執(zhí)行。這部分細(xì)節(jié)已經(jīng)由 Hibernate 掌管妥當(dāng),只有開發(fā)者在進(jìn)行系統(tǒng)性能調(diào)優(yōu)的時(shí)候才需要進(jìn)行了解。而MyBatis在這一塊沒有文檔說明,用戶需要對(duì)對(duì)象自己進(jìn)行詳細(xì)的管理。

第五方面:緩存機(jī)制

Hibernate緩存

Hibernate一級(jí)緩存是Session緩存,利用好一級(jí)緩存就需要對(duì)Session的生命周期進(jìn)行管理好。建議在一個(gè)Action操作中使用一個(gè)Session。一級(jí)緩存需要對(duì)Session進(jìn)行嚴(yán)格管理。
Hibernate二級(jí)緩存是SessionFactory級(jí)的緩存。 SessionFactory的緩存分為內(nèi)置緩存和外置緩存。內(nèi)置緩存中存放的是SessionFactory對(duì)象的一些集合屬性包含的數(shù)據(jù)(映射元素?fù)?jù)及預(yù)定SQL語句等),對(duì)于應(yīng)用程序來說,它是只讀的。外置緩存中存放的是數(shù)據(jù)庫數(shù)據(jù)的副本,其作用和一級(jí)緩存類似.二級(jí)緩存除了以內(nèi)存作為存儲(chǔ)介質(zhì)外,還可以選用硬盤等外部存儲(chǔ)設(shè)備。二級(jí)緩存稱為進(jìn)程級(jí)緩存或SessionFactory級(jí)緩存,它可以被所有session共享,它的生命周期伴隨著SessionFactory的生命周期存在和消亡。

MyBatis緩存

MyBatis 包含一個(gè)非常強(qiáng)大的查詢緩存特性,它可以非常方便地配置和定制。MyBatis 3 中的緩存實(shí)現(xiàn)的很多改進(jìn)都已經(jīng)實(shí)現(xiàn)了,使得它更加強(qiáng)大而且易于配置。
默認(rèn)情況下是沒有開啟緩存的,除了局部的 session 緩存,可以增強(qiáng)變現(xiàn)而且處理循環(huán) 依賴也是必須的。要開啟二級(jí)緩存,你需要在你的 SQL 映射文件中添加一行: <cache/>
字面上看就是這樣。這個(gè)簡單語句的效果如下:

  1. 映射語句文件中的所有 select 語句將會(huì)被緩存。
  2. 映射語句文件中的所有 insert,update 和 delete 語句會(huì)刷新緩存。
  3. 緩存會(huì)使用 Least Recently Used(LRU,最近最少使用的)算法來收回。
  4. 根據(jù)時(shí)間表(比如 no Flush Interval,沒有刷新間隔), 緩存不會(huì)以任何時(shí)間順序 來刷新。
  5. 緩存會(huì)存儲(chǔ)列表集合或?qū)ο?無論查詢方法返回什么)的 1024 個(gè)引用。
  6. 緩存會(huì)被視為是 read/write(可讀/可寫)的緩存,意味著對(duì)象檢索不是共享的,而 且可以安全地被調(diào)用者修改,而不干擾其他調(diào)用者或線程所做的潛在修改。

所有的這些屬性都可以通過緩存元素的屬性來修改。

比如: <cache eviction=”FIFO” flushInterval=”60000″ size=”512″ readOnly=”true”/>

這個(gè)更高級(jí)的配置創(chuàng)建了一個(gè) FIFO 緩存,并每隔 60 秒刷新,存數(shù)結(jié)果對(duì)象或列表的 512 個(gè)引用,而且返回的對(duì)象被認(rèn)為是只讀的,因此在不同線程中的調(diào)用者之間修改它們會(huì) 導(dǎo)致沖突。可用的收回策略有, 默認(rèn)的是 LRU:

  1. LRU – 最近最少使用的:移除最長時(shí)間不被使用的對(duì)象。
  2. FIFO – 先進(jìn)先出:按對(duì)象進(jìn)入緩存的順序來移除它們。
  3. SOFT – 軟引用:移除基于垃圾回收器狀態(tài)和軟引用規(guī)則的對(duì)象。
  4. WEAK – 弱引用:更積極地移除基于垃圾收集器狀態(tài)和弱引用規(guī)則的對(duì)象。

flushInterval(刷新間隔)可以被設(shè)置為任意的正整數(shù),而且它們代表一個(gè)合理的毫秒 形式的時(shí)間段。默認(rèn)情況是不設(shè)置,也就是沒有刷新間隔,緩存僅僅調(diào)用語句時(shí)刷新。

size(引用數(shù)目)可以被設(shè)置為任意正整數(shù),要記住你緩存的對(duì)象數(shù)目和你運(yùn)行環(huán)境的 可用內(nèi)存資源數(shù)目。默認(rèn)值是1024。

readOnly(只讀)屬性可以被設(shè)置為 true 或 false。只讀的緩存會(huì)給所有調(diào)用者返回緩 存對(duì)象的相同實(shí)例。因此這些對(duì)象不能被修改。這提供了很重要的性能優(yōu)勢??勺x寫的緩存 會(huì)返回緩存對(duì)象的拷貝(通過序列化) 。這會(huì)慢一些,但是安全,因此默認(rèn)是 false。

相同點(diǎn):Hibernate和Mybatis的二級(jí)緩存除了采用系統(tǒng)默認(rèn)的緩存機(jī)制外,都可以通過實(shí)現(xiàn)你自己的緩存或?yàn)槠渌谌骄彺娣桨?,?chuàng)建適配器來完全覆蓋緩存行為。

不同點(diǎn):Hibernate的二級(jí)緩存配置在SessionFactory生成的配置文件中進(jìn)行詳細(xì)配置,然后再在具體的表-對(duì)象映射中配置是那種緩存。

MyBatis的二級(jí)緩存配置都是在每個(gè)具體的表-對(duì)象映射中進(jìn)行詳細(xì)配置,這樣針對(duì)不同的表可以自定義不同的緩存機(jī)制。并且Mybatis可以在命名空間中共享相同的緩存配置和實(shí)例,通過Cache-ref來實(shí)現(xiàn)。

兩者比較:因?yàn)镠ibernate對(duì)查詢對(duì)象有著良好的管理機(jī)制,用戶無需關(guān)心SQL。所以在使用二級(jí)緩存時(shí)如果出現(xiàn)臟數(shù)據(jù),系統(tǒng)會(huì)報(bào)出錯(cuò)誤并提示。

而MyBatis在這一方面,使用二級(jí)緩存時(shí)需要特別小心。如果不能完全確定數(shù)據(jù)更新操作的波及范圍,避免Cache的盲目使用。否則,臟數(shù)據(jù)的出現(xiàn)會(huì)給系統(tǒng)的正常運(yùn)行帶來很大的隱患。

第六方面:總結(jié)
對(duì)于總結(jié),大家可以到各大java論壇去看一看

相同點(diǎn):Hibernate與MyBatis都可以是通過SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session來開啟執(zhí)行事務(wù)和SQL語句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。

  • Hibernate和MyBatis都支持JDBC和JTA事務(wù)處理。

Mybatis優(yōu)勢

  • MyBatis可以進(jìn)行更為細(xì)致的SQL優(yōu)化,可以減少查詢字段。
  • MyBatis容易掌握,而Hibernate門檻較高。

Hibernate優(yōu)勢

  • Hibernate的DAO層開發(fā)比MyBatis簡單,Mybatis需要維護(hù)SQL和結(jié)果映射。
  • Hibernate對(duì)對(duì)象的維護(hù)和緩存要比MyBatis好,對(duì)增刪改查的對(duì)象的維護(hù)要方便。
  • Hibernate數(shù)據(jù)庫移植性很好,MyBatis的數(shù)據(jù)庫移植性不好,不同的數(shù)據(jù)庫需要寫不同SQL。
  • Hibernate有更好的二級(jí)緩存機(jī)制,可以使用第三方緩存。MyBatis本身提供的緩存機(jī)制不佳。

他人總結(jié)

  • Hibernate功能強(qiáng)大,數(shù)據(jù)庫無關(guān)性好,O/R映射能力強(qiáng),如果你對(duì)Hibernate相當(dāng)精通,而且對(duì)Hibernate進(jìn)行了適當(dāng)?shù)姆庋b,那么你的項(xiàng)目整個(gè)持久層代碼會(huì)相當(dāng)簡單,需要寫的代碼很少,開發(fā)速度很快,非常爽。
  • Hibernate的缺點(diǎn)就是學(xué)習(xí)門檻不低,要精通門檻更高,而且怎么設(shè)計(jì)O/R映射,在性能和對(duì)象模型之間如何權(quán)衡取得平衡,以及怎樣用好Hibernate方面需要你的經(jīng)驗(yàn)和能力都很強(qiáng)才行。
  • iBATIS入門簡單,即學(xué)即用,提供了數(shù)據(jù)庫查詢的自動(dòng)對(duì)象綁定功能,而且延續(xù)了很好的SQL使用經(jīng)驗(yàn),對(duì)于沒有那么高的對(duì)象模型要求的項(xiàng)目來說,相當(dāng)完美。
  • iBATIS的缺點(diǎn)就是框架還是比較簡陋,功能尚有缺失,雖然簡化了數(shù)據(jù)綁定代碼,但是整個(gè)底層數(shù)據(jù)庫查詢實(shí)際還是要自己寫的,工作量也比較大,而且不太容易適應(yīng)快速數(shù)據(jù)庫修改。

16.filter與servlet的比較

一、概念:
1、servlet:servlet是一種運(yùn)行服務(wù)器端的java應(yīng)用程序,具有獨(dú)立于平臺(tái)和協(xié)議的特性,并且可以動(dòng)態(tài)的生成web頁面,它工作在客戶端請求與服務(wù)器響應(yīng)的中間層。
2、filter:filter是一個(gè)可以復(fù)用的代碼片段,可以用來轉(zhuǎn)換HTTP請求、響應(yīng)和頭信息。Filter不像Servlet,它不能產(chǎn)生一個(gè)請求或者響應(yīng),它只是修改對(duì)某一資源的請求,或者修改從某一的響應(yīng)。
二、生命周期:
1、servlet:servlet的生命周期始于它被裝入web服務(wù)器的內(nèi)存時(shí),并在web服務(wù)器終止或重新裝入servlet時(shí)結(jié)束。servlet一旦被裝入web服務(wù)器,一般不會(huì)從web服務(wù)器內(nèi)存中刪除,直至web服務(wù)器關(guān)閉或重新結(jié)束。
(1)、裝入:啟動(dòng)服務(wù)器時(shí)加載Servlet的實(shí)例;
(2)、初始化:web服務(wù)器啟動(dòng)時(shí)或web服務(wù)器接收到請求時(shí),或者兩者之間的某個(gè)時(shí)刻啟動(dòng)。初始化工作有init()方法負(fù)責(zé)執(zhí)行完成;
(3)、調(diào)用:從第一次到以后的多次訪問,都是只調(diào)用doGet()或doPost()方法;
(4)、銷毀:停止服務(wù)器時(shí)調(diào)用destroy()方法,銷毀實(shí)例。
2、filter:(一定要實(shí)現(xiàn)javax.servlet包的Filter接口的三個(gè)方法init()、doFilter()、destroy(),空實(shí)現(xiàn)也行)
(1)、啟動(dòng)服務(wù)器時(shí)加載過濾器的實(shí)例,并調(diào)用init()方法來初始化實(shí)例;
(2)、每一次請求時(shí)都只調(diào)用方法doFilter()進(jìn)行處理;
(3)、停止服務(wù)器時(shí)調(diào)用destroy()方法,銷毀實(shí)例。
三、職責(zé)
1、servlet
創(chuàng)建并返回一個(gè)包含基于客戶請求性質(zhì)的動(dòng)態(tài)內(nèi)容的完整的html頁面;
創(chuàng)建可嵌入到現(xiàn)有的html頁面中的一部分html頁面(html片段);
讀取客戶端發(fā)來的隱藏?cái)?shù)據(jù);
讀取客戶端發(fā)來的顯示數(shù)據(jù);
與其他服務(wù)器資源(包括數(shù)據(jù)庫和java的應(yīng)用程序)進(jìn)行通信;
通過狀態(tài)代碼和響應(yīng)頭向客戶端發(fā)送隱藏?cái)?shù)據(jù)。
2、filter:
filter能夠在一個(gè)請求到達(dá)servlet之前預(yù)處理用戶請求,也可以在離開servlet時(shí)處理http響應(yīng):
在執(zhí)行servlet之前,首先執(zhí)行filter程序,并為之做一些預(yù)處理工作;
根據(jù)程序需要修改請求和響應(yīng);
在servlet被調(diào)用之后截獲servlet的執(zhí)行
四、區(qū)別:
1、servlet 流程是短的,url傳來之后,就對(duì)其進(jìn)行處理,之后返回或轉(zhuǎn)向到某一自己指定的頁面。它主要用來在 業(yè)務(wù)處理之前進(jìn)行控制.
2、filter 流程是線性的, url傳來之后,檢查之后,可保持原來的流程繼續(xù)向下執(zhí)行,被下一個(gè)filter, servlet接收等,而servlet 處理之后,不會(huì)繼續(xù)向下傳遞。filter功能可用來保持流程繼續(xù)按照原來的方式進(jìn)行下去,或者主導(dǎo)流程,而servlet的功能主要用來主導(dǎo)流程。
filter可用來進(jìn)行字符編碼的過濾,檢測用戶是否登陸的過濾,禁止頁面緩存等

17.攔截器和過濾器的區(qū)別

①攔截器是基于java的反射機(jī)制的,而過濾器是基于函數(shù)回調(diào)。
②攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
③攔截器只能對(duì)action請求起作用,而過濾器則可以對(duì)幾乎所有的請求起作用。
④攔截器可以訪問action上下文、值棧里的對(duì)象,而過濾器不能訪問。
⑤在action的生命周期中,攔截器可以多次被調(diào)用,而過濾器只能在容器初始化時(shí)被調(diào)用一次。
⑥攔截器可以獲取IOC容器中的各個(gè)bean,而過濾器就不行,這點(diǎn)很重要,在攔截器里注入一個(gè)service,可以調(diào)用業(yè)務(wù)邏輯。

Spring的攔截器與Servlet的Filter有相似之處,比如二者都是AOP編程思想的體現(xiàn),都能實(shí)現(xiàn)權(quán)限檢查、日志記錄等。
不同的是:
使用范圍不同:Filter是Servlet規(guī)范規(guī)定的,只能用于Web程序中。而攔截器既可以用于Web程序,也可以用于Application、Swing程序中。
規(guī)范不同:Filter是在Servlet規(guī)范中定義的,是Servlet容器支持的。而攔截器是在Spring容器內(nèi)的,是Spring框架支持的。
使用的資源不同:同其他的代碼塊一樣,攔截器也是一個(gè)Spring的組件,歸Spring管理,配置在Spring文件中,因此能使用Spring里的任何資源、對(duì)象,例如Service對(duì)象、數(shù)據(jù)源、事務(wù)管理等,通過IoC注入到攔截器即可;而Filter則不能。

深度不同:Filter在只在Servlet前后起作用。而攔截器能夠深入到方法前后、異常拋出前后等,因此攔截器的使用具有更大的彈性。所以在Spring構(gòu)架的程序中,要優(yōu)先使用攔截器。

實(shí)際上Filter和Servlet極其相似,區(qū)別只是Filter不能直接對(duì)用戶生成響應(yīng)。實(shí)際上Filter里doFilter()方法里的代碼就是從多個(gè)Servlet的service()方法里抽取的通用代碼,通過使用Filter可以實(shí)現(xiàn)更好的復(fù)用。

filter是一個(gè)可以復(fù)用的代碼片段,可以用來轉(zhuǎn)換HTTP請求、響應(yīng)和頭信息。Filter不像Servlet,它不能產(chǎn)生一個(gè)請求或者響 應(yīng),它只是修改對(duì)某一資源的請求,或者修改從某一的響應(yīng)。

18.數(shù)據(jù)庫設(shè)計(jì)6個(gè)注意點(diǎn)+2點(diǎn)總結(jié)

1、主鍵與外鍵
一般而言,一個(gè)實(shí)體不能既無主鍵又無外鍵。沒有主鍵就沒有實(shí)體。
2、區(qū)別對(duì)待不同的表
基本表與統(tǒng)計(jì)表、中間表、臨時(shí)表等不同,有以下特性
a、原始性?;颈碇械挠涗浭窃紨?shù)據(jù)(基礎(chǔ)數(shù)據(jù))的記錄。
b、演繹性。由基本按照一定的業(yè)務(wù)原則可以生成統(tǒng)計(jì)表和臨時(shí)表的數(shù)據(jù)。
c、穩(wěn)定性?;颈淼慕Y(jié)構(gòu)是相對(duì)穩(wěn)定的,表中的記錄是要長期保存的。
所以在設(shè)計(jì)數(shù)據(jù)庫的時(shí)候,要盡量將基本表和其它中間表、統(tǒng)計(jì)表區(qū)別開來。應(yīng)盡量滿足第三范式。其它表可以適當(dāng)?shù)慕档头妒?。但是不管怎樣,滿足第三范式的數(shù)據(jù)庫設(shè)計(jì),往往不是最好的設(shè)計(jì)。為了提高數(shù)據(jù)庫的運(yùn)行效率,常常需要降低范式標(biāo)準(zhǔn):適當(dāng)增加冗余,達(dá)到以空間換時(shí)間的目的。
3、范式理解和冗余的分類
第一范式:1NF是對(duì)屬性的原子性約束,要求屬性具有原子性,不可再分解;
第二范式:2NF是對(duì)記錄的惟一性約束,要求記錄有惟一標(biāo)識(shí),即實(shí)體的惟一性;
第三范式:3NF是對(duì)字段冗余性的約束,即任何字段不能由其他字段派生出來,它要求字段沒有冗余。
有時(shí)為了提高運(yùn)行效率,就必須降低范式標(biāo)準(zhǔn),適當(dāng)保留冗余數(shù)據(jù)。具體做法是:在概念數(shù)據(jù)模型設(shè)計(jì)時(shí)遵守第三范式,降低范式標(biāo)準(zhǔn)的工作放到物理數(shù)據(jù)模型設(shè)計(jì)時(shí)考慮。降低范式就是增加字段,允許冗余。
但是冗余是有區(qū)別的,主鍵與外鍵在多表中的重復(fù)出現(xiàn), 不屬于數(shù)據(jù)冗余,這個(gè)概念必須清楚,事實(shí)上有許多人還不清楚。
a、非鍵字段的重復(fù)出現(xiàn), 才是數(shù)據(jù)冗余!而且是一種低級(jí)冗余,即重復(fù)性的冗余。
b、高級(jí)冗余不是字段的重復(fù)出現(xiàn),而是字段的派生出現(xiàn)。
  〖例4〗:商品中的“單價(jià)、數(shù)量、金額”三個(gè)字段,“金額”就是由“單價(jià)”乘以“數(shù)量”派生出來的,它就是冗余,而且是一種高級(jí)冗余。冗余的目的是為了提高處理速度。只有低級(jí)冗余才會(huì)增加數(shù)據(jù)的不一致性,因?yàn)橥粩?shù)據(jù),可能從不同時(shí)間、地點(diǎn)、角色上多次錄入。因此,我們提倡高級(jí)冗余(派生性冗余),反對(duì)低級(jí)冗余(重復(fù)性冗余)。

反規(guī)范設(shè)計(jì)的數(shù)據(jù)需要額外的工作來維護(hù)數(shù)據(jù)的完整性,一般可以通過以下幾種方式進(jìn)行
a、應(yīng)用邏輯
在應(yīng)用程序的事務(wù)中對(duì)同一數(shù)據(jù)的多處存儲(chǔ)進(jìn)行維護(hù)。這種方式比較難于管理,一個(gè)維護(hù)邏輯很容易出現(xiàn)在多個(gè)應(yīng)用程序當(dāng)中,容易遺漏。
b、批處理維護(hù)
由批處理程序批量的處理所有的非規(guī)范化關(guān)系涉及的數(shù)據(jù)。一般定期運(yùn)行,運(yùn)行間隔根據(jù)業(yè)務(wù)來決定,并且可以利用Job來自動(dòng)運(yùn)行批處理程序??捎糜趯?duì)冗余數(shù)據(jù)的實(shí)時(shí)性要求不高或者有一定規(guī)則的環(huán)境。
c、觸發(fā)器
在數(shù)據(jù)庫端建立觸發(fā)器,對(duì)原數(shù)據(jù)的修改會(huì)立即觸發(fā)對(duì)冗余列的修改。可用于對(duì)數(shù)據(jù)實(shí)時(shí)性要求較高的環(huán)境,但同時(shí)會(huì)降低數(shù)據(jù)的插入和更新速度。

4、重視視圖、物化視圖技術(shù)在數(shù)據(jù)庫的使用
a、簡化查詢
b、隱藏?cái)?shù)據(jù)庫結(jié)構(gòu),權(quán)限管理,安全
c、物化視圖進(jìn)行數(shù)據(jù)預(yù)準(zhǔn)備,性能

5、數(shù)據(jù)完整性
盡量在表級(jí)約束條件(5個(gè)=2列級(jí)+2表級(jí)+1表間)實(shí)現(xiàn),實(shí)現(xiàn)不了的復(fù)雜業(yè)務(wù)約束再進(jìn)行觸發(fā)器和存儲(chǔ)過程實(shí)現(xiàn)。

6、要善于識(shí)別與正確處理多對(duì)多的關(guān)系
  若兩個(gè)實(shí)體之間存在多對(duì)多的關(guān)系,則應(yīng)消除這種關(guān)系。消除的辦法是,在兩者之間增加第三個(gè)實(shí)體。這樣,原來一個(gè)多對(duì)多的關(guān)系,現(xiàn)在變?yōu)閮蓚€(gè)一對(duì)多的關(guān)系。要將原來兩個(gè)實(shí)體的屬性合理地分配到三個(gè)實(shí)體中去。這里的第三個(gè)實(shí)體,實(shí)質(zhì)上是一個(gè)較復(fù)雜的關(guān)系,它對(duì)應(yīng)一張基本表。一般來講,數(shù)據(jù)庫設(shè)計(jì)工具不能識(shí)別多對(duì)多的關(guān)系,但能處理多對(duì)多的關(guān)系。

〖例3〗:在“圖書館信息系統(tǒng)”中,“圖書”是一個(gè)實(shí)體,“讀者”也是一個(gè)實(shí)體。這兩個(gè)實(shí)體之間的關(guān)系,是一個(gè)典型的多對(duì)多關(guān)系:一本圖書在不同時(shí)間可以被多個(gè)讀者借閱,一個(gè)讀者又可以借多本圖書。為此,要在二者之間增加第三個(gè)實(shí)體,該實(shí)體取名為“借還書”,它的屬性為:借還時(shí)間、借還標(biāo)志(0表示借書,1表示還書),另外,它還應(yīng)該有兩個(gè)外鍵(“圖書”的主鍵,“讀者”的主鍵),使它能與“圖書”和“讀者”連接。

===================================================================================

1、 防止數(shù)據(jù)庫設(shè)計(jì)打補(bǔ)丁的方法是“三少原則”
   (1) 一個(gè)數(shù)據(jù)庫中表的個(gè)數(shù)越少越好。只有表的個(gè)數(shù)少了,才能說明系統(tǒng)的E--R圖少而精,去掉了重復(fù)的多余的實(shí)體,形成了對(duì)客觀世界的高度抽象,進(jìn)行了系統(tǒng)的數(shù)據(jù)集成,防止了打補(bǔ)丁式的設(shè)計(jì);
   (2) 一個(gè)表中組合主鍵的字段個(gè)數(shù)越少越好。因?yàn)橹麈I的作用,一是建主鍵索引,二是做為子表的外鍵,所以組合主鍵的字段個(gè)數(shù)少了,不僅節(jié)省了運(yùn)行時(shí)間,而且節(jié)省了索引存儲(chǔ)空間;
   (3) 一個(gè)表中的字段個(gè)數(shù)越少越好。只有字段的個(gè)數(shù)少了,才能說明在系統(tǒng)中不存在數(shù)據(jù)重復(fù),且很少有數(shù)據(jù)冗余,更重要的是督促讀者學(xué)會(huì)“列變行”,這樣就防止了將子表中的字段拉入到主表中去,在主表中留下許多空余的字段。所謂“列變行”,就是將主表中的一部分內(nèi)容拉出去,另外單獨(dú)建一個(gè)子表。這個(gè)方法很簡單,有的人就是不習(xí)慣、不采納、不執(zhí)行。

數(shù)據(jù)庫設(shè)計(jì)的實(shí)用原則是:在數(shù)據(jù)冗余和處理速度之間找到合適的平衡點(diǎn)?!叭佟笔且粋€(gè)整體概念,綜合觀點(diǎn),不能孤立某一個(gè)原則。該原則是相對(duì)的,不是絕對(duì)的。“三多”原則肯定是錯(cuò)誤的。試想:若覆蓋系統(tǒng)同樣的功能,一百個(gè)實(shí)體(共一千個(gè)屬性) 的E--R圖,肯定比二百個(gè)實(shí)體(共二千個(gè)屬性) 的E--R圖,要好得多。
  提倡“三少”原則,是叫讀者學(xué)會(huì)利用數(shù)據(jù)庫設(shè)計(jì)技術(shù)進(jìn)行系統(tǒng)的數(shù)據(jù)集成。數(shù)據(jù)集成的步驟是將文件系統(tǒng)集成為應(yīng)用數(shù)據(jù)庫,將應(yīng)用數(shù)據(jù)庫集成為主題數(shù)據(jù)庫,將主題數(shù)據(jù)庫集成為全局綜合數(shù)據(jù)庫。集成的程度越高,數(shù)據(jù)共享性就越強(qiáng),信息孤島現(xiàn)象就越少,整個(gè)企業(yè)信息系統(tǒng)的全局E—R圖中實(shí)體的個(gè)數(shù)、主鍵的個(gè)數(shù)、屬性的個(gè)數(shù)就會(huì)越少。
  提倡“三少”原則的目的,是防止讀者利用打補(bǔ)丁技術(shù),不斷地對(duì)數(shù)據(jù)庫進(jìn)行增刪改,使企業(yè)數(shù)據(jù)庫變成了隨意設(shè)計(jì)數(shù)據(jù)庫表的“垃圾堆”,或數(shù)據(jù)庫表的“大雜院”,最后造成數(shù)據(jù)庫中的基本表、代碼表、中間表、臨時(shí)表雜亂無章,不計(jì)其數(shù),導(dǎo)致企事業(yè)單位的信息系統(tǒng)無法維護(hù)而癱瘓。

2、提高數(shù)據(jù)庫運(yùn)行效率的辦法
  在給定的系統(tǒng)硬件和系統(tǒng)軟件條件下,提高數(shù)據(jù)庫系統(tǒng)的運(yùn)行效率的辦法是:
   (1) 在數(shù)據(jù)庫物理設(shè)計(jì)時(shí),降低范式,增加冗余, 少用觸發(fā)器, 多用存儲(chǔ)過程。
   (2) 當(dāng)計(jì)算非常復(fù)雜、而且記錄條數(shù)非常巨大時(shí)(例如一千萬條),復(fù)雜計(jì)算要先在數(shù)據(jù)庫外面,以文件系統(tǒng)方式用C++語言計(jì)算處理完成之后,最后才入庫追加到表中去。這是電信計(jì)費(fèi)系統(tǒng)設(shè)計(jì)的經(jīng)驗(yàn)。
   (3) 發(fā)現(xiàn)某個(gè)表的記錄太多,例如超過一千萬條,則要對(duì)該表進(jìn)行水平分割(oracle的分區(qū)表很強(qiáng)大,可代替此操作)。水平分割的做法是,以該表主鍵PK的某個(gè)值為界線,將該表的記錄水平分割為兩個(gè)表。若發(fā)現(xiàn)某個(gè)表的字段太多,例如超過八十個(gè),則垂直分割該表,將原來的一個(gè)表分解為兩個(gè)表。
   (4) 對(duì)數(shù)據(jù)庫管理系統(tǒng)DBMS進(jìn)行系統(tǒng)優(yōu)化,即優(yōu)化各種系統(tǒng)參數(shù),如緩沖區(qū)個(gè)數(shù)。
   (5) 在使用面向數(shù)據(jù)的SQL語言進(jìn)行程序設(shè)計(jì)時(shí),盡量采取優(yōu)化算法。
總之,要提高數(shù)據(jù)庫的運(yùn)行效率,必須從數(shù)據(jù)庫系統(tǒng)級(jí)優(yōu)化、數(shù)據(jù)庫設(shè)計(jì)級(jí)優(yōu)化、程序?qū)崿F(xiàn)級(jí)優(yōu)化,這三個(gè)層次上同時(shí)下功夫。

19.mysql ACID與四種隔離級(jí)別歸納總結(jié)

A(atomicity)原子性:
  即事務(wù)要么全部做完,要么全部不做,不會(huì)出現(xiàn)只做一部分的情形,如A給B轉(zhuǎn)帳,不會(huì)出現(xiàn)A的錢少了,B的錢卻沒有增加的情況
C(consistency)一致性:
  指的是事務(wù)從一個(gè)狀態(tài)到另一個(gè)狀態(tài)是一致的,如A減少了100,B不可能只增加30。
I(isolation)隔離性:
  即一個(gè)事務(wù)在沒有完成數(shù)據(jù)的提交修改時(shí),對(duì)其它事務(wù)是不可見的。當(dāng)然這里有個(gè)隔離級(jí)別的概念,在不同隔離級(jí)別下,這里會(huì)有不同的表現(xiàn)形式
D(durability)持久性:
  一旦事務(wù)提交,則所做修改就會(huì)被永久保存到數(shù)據(jù)庫中。

在說隔離級(jí)別之前,我們先說如下幾個(gè)概念:
臟讀:
  一個(gè)事務(wù)對(duì)數(shù)據(jù)進(jìn)行增刪改,但并沒有提交,但另一事務(wù)卻能讀到未提交的數(shù)據(jù)
不可重復(fù)讀:
  一事務(wù)對(duì)數(shù)據(jù)進(jìn)行了更新或刪除操作,另一事務(wù)兩次查詢的數(shù)據(jù)不一致
幻讀:
  一事務(wù)對(duì)數(shù)據(jù)進(jìn)行了新增操作,另一事務(wù)兩次查詢結(jié)果不一致。

我們看到不可重復(fù)讀與幻讀好像好類似,但其實(shí)它們是有很大的不同,不可重復(fù)讀主要體現(xiàn)在update與delete,而幻讀主要體現(xiàn)在insert,從實(shí)現(xiàn)層面上講,要解決不可重復(fù)讀,我們只需要對(duì)查詢的數(shù)據(jù)進(jìn)行加鎖就可以實(shí)現(xiàn),此時(shí)update與delete這些行都會(huì)阻塞等待,但是insert依舊可以,避免不了幻讀,而要解決幻讀,必須對(duì)其行與行之前也加鎖,在mysql中,是通過next key lock(行鎖+gap lock)來實(shí)現(xiàn)的。

隔離級(jí)別:
read uncommited未提交讀:
  隔離級(jí)別為0,會(huì)有臟讀,不可重復(fù)讀,幻讀
read commit提交讀:
  隔離級(jí)別為1,不會(huì)有臟讀,但有不可重復(fù)讀,幻讀
repeatable read可重復(fù)讀:
  隔離級(jí)別為2,不會(huì)有臟讀,不可重復(fù)讀,但依舊會(huì)有幻讀。但為什么說mysql中的repeatable read解決了幻讀?本來是會(huì)有幻讀的,但是它采用了next key lock加上for update來避免,InnoDB提供了這樣一種機(jī)制,通過加鎖去查詢可以得到最新的數(shù)據(jù),如兩個(gè)事務(wù)同時(shí)開啟,A事務(wù)插入了一條數(shù)據(jù),并提交,B事務(wù)去查select * from t,此時(shí)B是不能查詢到A事務(wù)提交的數(shù)據(jù)的,但是加多一個(gè)for update,即select * from t for update,就能查找剛剛A事務(wù)插入的數(shù)據(jù)。所以我們才說mysql在repeatable read隔離級(jí)別下可以避免幻讀的原因,記得加for update。
serializable可序列化:
  隔離級(jí)別為3,不會(huì)有臟讀,不可重復(fù)讀,幻讀。但效率最低,并發(fā)性能最差,一般情況下不會(huì)使用。

20.java虛擬機(jī)類加載機(jī)制

加載:階段主要完成三件事,即通過一個(gè)類的全限定名來獲取定義此類的二進(jìn)制字節(jié)流,將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu),在Java堆中生成一個(gè)代表此類的Class對(duì)象,作為訪問方法區(qū)這些數(shù)據(jù)的入口。
驗(yàn)證:確保Class文件的字節(jié)流中包含信息符合當(dāng)前虛擬機(jī)要求,不會(huì)危害虛擬機(jī)自身安全。主要包括四種驗(yàn)證:文件格式驗(yàn)證、元數(shù)據(jù)驗(yàn)證、字節(jié)碼驗(yàn)證、符號(hào)引用驗(yàn)證。
準(zhǔn)備:僅僅為類變量(即static修飾的字段變量)分配內(nèi)存并且設(shè)置該類變量的初始值即零值,這里不包含用final修飾的static,因?yàn)閒inal在編 譯的時(shí)候就會(huì)分配了,同時(shí)這里也不會(huì)為實(shí)例變量分配初始化。類變量會(huì)分配在方法區(qū)中,而實(shí)例變量是會(huì)隨著對(duì)象一起分配到Java堆中。
解析:主要就是將常量池中的符號(hào)引用替換為直接引用的過程。
初始化:階段依舊是初始化類變量和其他資源,這里將執(zhí)行用戶的static字段和靜態(tài)語句塊的賦值操作。這個(gè)過程就是執(zhí)行類構(gòu)造器方法的過程。
類加載器的分類:啟動(dòng)類加載器、擴(kuò)展類類加載器、應(yīng)用程序類加載器。

21.Lock和synchronized有以下幾點(diǎn)不同

1).Lock是一個(gè)接口,而synchronized是Java中的關(guān)鍵字,synchronized是內(nèi)置的語言;
2).synchronized在發(fā)生異常時(shí),會(huì)自動(dòng)釋放線程占有的鎖,因此不會(huì)導(dǎo)致死鎖現(xiàn)象的發(fā)生;而Lock在發(fā)生異常時(shí),如果沒有主動(dòng)通過unlock()去釋放鎖,而很可能造成死鎖的現(xiàn)象,因此使用Lock時(shí)需要在finally塊中釋放鎖;
3).Lock可以讓等待鎖的線程響應(yīng)中斷,而synchronized卻不行,使用synchronized時(shí),等待的線程會(huì)一直等待下去,不能夠響應(yīng)中斷;
4).通過Lock可以知道有沒有成功獲取鎖,而synchronized卻無法辦到。
5).Lock可以提高多個(gè)線程進(jìn)行讀操作的效率。
在性能上來說,如果競爭資源不激烈,兩者的性能是差不多的,而當(dāng)競爭資源非常激烈時(shí)(即有大量線程同時(shí)競爭),此時(shí)Lock的性能要遠(yuǎn)遠(yuǎn)優(yōu)于synchronized。所以說,在具體使用時(shí)要根據(jù)適當(dāng)情況選擇。

22.緩存穿透,緩存擊穿,緩存雪崩解決方案分析

緩存穿透

緩存穿透是指查詢一個(gè)一定不存在的數(shù)據(jù),由于緩存是不命中時(shí)被動(dòng)寫的,并且出于容錯(cuò)考慮,如果從存儲(chǔ)層查不到數(shù)據(jù)則不寫入緩存,這將導(dǎo)致這個(gè)不存在的數(shù)據(jù)每次請求都要到存儲(chǔ)層去查詢,失去了緩存的意義。在流量大時(shí),可能DB就掛掉了,要是有人利用不存在的key頻繁攻擊我們的應(yīng)用,這就是漏洞。

解決方案

有很多種方法可以有效地解決緩存穿透問題,最常見的則是采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的bitmap中,一個(gè)一定不存在的數(shù)據(jù)會(huì)被 這個(gè)bitmap攔截掉,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢壓力。另外也有一個(gè)更為簡單粗暴的方法(我們采用的就是這種),如果一個(gè)查詢返回的數(shù)據(jù)為空(不管是數(shù) 據(jù)不存在,還是系統(tǒng)故障),我們?nèi)匀话堰@個(gè)空結(jié)果進(jìn)行緩存,但它的過期時(shí)間會(huì)很短,最長不超過五分鐘。

緩存雪崩

緩存雪崩是指在我們設(shè)置緩存時(shí)采用了相同的過期時(shí)間,導(dǎo)致緩存在某一時(shí)刻同時(shí)失效,請求全部轉(zhuǎn)發(fā)到DB,DB瞬時(shí)壓力過重雪崩。

解決方案

緩存失效時(shí)的雪崩效應(yīng)對(duì)底層系統(tǒng)的沖擊非??膳?。大多數(shù)系統(tǒng)設(shè)計(jì)者考慮用加鎖或者隊(duì)列的方式保證緩存的單線 程(進(jìn)程)寫,從而避免失效時(shí)大量的并發(fā)請求落到底層存儲(chǔ)系統(tǒng)上。這里分享一個(gè)簡單方案就時(shí)講緩存失效時(shí)間分散開,比如我們可以在原有的失效時(shí)間基礎(chǔ)上增加一個(gè)隨機(jī)值,比如1-5分鐘隨機(jī),這樣每一個(gè)緩存的過期時(shí)間的重復(fù)率就會(huì)降低,就很難引發(fā)集體失效的事件。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容