java 基礎(chǔ)備忘

1.內(nèi)存泄露

內(nèi)存泄漏兩種情況:

在堆中申請的空間沒有被釋放(虛擬機(jī)gc可以解決)

對象已不在使用,但仍然在內(nèi)存中保留著

Java中主要的內(nèi)存泄漏:

靜態(tài)集合類闪金,容器中的對象在程序結(jié)束之前都不會(huì)被釋放

數(shù)據(jù)庫連接、網(wǎng)絡(luò)連接哥牍、IO連接

監(jiān)聽器

變量不合理的作用域毕泌,成員變量在使用后依然存在。(解決:將變量設(shè)為局部變量)

單例造成內(nèi)存泄漏

2.switch

注:在java中switch后的表達(dá)式的類型只能為以下幾種:byte嗅辣、short撼泛、char、int(在Java1.6中是這樣)澡谭,在java1.7后支持了對string的判斷.long不可以愿题,會(huì)出現(xiàn)精度丟失

3.LRU算法

LRU(Least?recently?used,最近最少使用)算法根據(jù)數(shù)據(jù)的歷史訪問記錄來進(jìn)行淘汰數(shù)據(jù)蛙奖,其核心思想是“如果數(shù)據(jù)最近被訪問過潘酗,那么將來被訪問的幾率也更高”。

1.?新數(shù)據(jù)插入到鏈表頭部雁仲;

2.?每當(dāng)緩存命中(即緩存數(shù)據(jù)被訪問)仔夺,則將數(shù)據(jù)移到鏈表頭部;

3.?當(dāng)鏈表滿的時(shí)候攒砖,將鏈表尾部的數(shù)據(jù)丟棄缸兔。

可以使用LinkedHashMap日裙、FIFO、HashMap+鏈表實(shí)現(xiàn)

4.內(nèi)存溢出

1惰蜜, ? ?java Heap 溢出

一般的異常信息:java.lang.OutOfMemoryError:Java heap space

java堆用于存儲(chǔ)對象實(shí)例昂拂,我們只要不斷的創(chuàng)建對象,并且保證GC Roots到對象之間有可達(dá)路徑來避免垃圾回收機(jī)制清除這些對象抛猖,就會(huì)在對象數(shù)量達(dá)到最大堆容量限制后產(chǎn)生內(nèi)存溢出異常格侯。

可能原因:一個(gè)原因是真不夠,另一個(gè)原因是程序中有死循環(huán)财著×模或者說有可能是內(nèi)存溢出也有可能是內(nèi)存泄露,后者可能會(huì)導(dǎo)致前者瓢宦,所以要先排除內(nèi)存泄露的可能碎连。

出現(xiàn)這種異常向族,一般手段是先通過內(nèi)存映像分析工具(如Eclipse Memory Analyzer)對dump出來的堆轉(zhuǎn)存快照進(jìn)行分析悬嗓,重點(diǎn)是確認(rèn)內(nèi)存中的對象是否是必要的桐智,先分清是因?yàn)閮?nèi)存泄漏(Memory Leak)還是內(nèi)存溢出(Memory Overflow)得糜。

如果是內(nèi)存泄漏诫肠,可進(jìn)一步通過工具(如Jrockit等工具)查看泄漏對象到GC Roots的引用鏈躁锡。于是就能找到泄漏對象時(shí)通過怎樣的路徑與GC Roots相關(guān)聯(lián)并導(dǎo)致垃圾收集器無法自動(dòng)回收煤伟。

如果不存在泄漏瞭吃,那就應(yīng)該檢查虛擬機(jī)的參數(shù)(-Xmx與-Xms)的設(shè)置是否適當(dāng)恐似。

2杜跷,???虛擬機(jī)棧和本地方法棧溢出

當(dāng)棧深度超過虛擬機(jī)分配給線程的棧大小時(shí),將拋出StackOverflowError異常(無限遞歸)

當(dāng)再申請新的內(nèi)存時(shí)矫夷,虛擬機(jī)分配給線程的內(nèi)存大小中無法再分配新的內(nèi)存葛闷,則拋出OutOfMemoryError異常(不斷創(chuàng)建新線程)

這里需要注意當(dāng)棧的大小越大可分配的線程數(shù)就越少。

3双藕,???運(yùn)行時(shí)常量池溢出(JDK6及之前)

異常信息:java.lang.OutOfMemoryError:PermGen space

如果要向運(yùn)行時(shí)常量池中添加內(nèi)容淑趾,最簡單的做法就是使用String.intern()這個(gè)Native方法。該方法的作用是:如果池中已經(jīng)包含一個(gè)等于此String的字符串忧陪,則返回代表池中這個(gè)字符串的String對象扣泊;否則,將此String對象包含的字符串添加到常量池中嘶摊,并且返回此String對象的引用延蟹。由于常量池分配在方法區(qū)內(nèi),我們可以通過-XX:PermSize和-XX:MaxPermSize限制方法區(qū)的大小叶堆,從而間接限制其中常量池的容量阱飘。

4,???方法區(qū)溢出

方法區(qū)用于存放Class的相關(guān)信息,如類名俯萌、訪問修飾符果录、常量池、字段描述咐熙、方法描述等。

異常信息:java.lang.OutOfMemoryError:PermGen space

方法區(qū)溢出也是一種常見的內(nèi)存溢出異常辨萍,一個(gè)類如果要被垃圾收集器回收棋恼,判定條件是很苛刻的。在經(jīng)常動(dòng)態(tài)生成大量Class的應(yīng)用中锈玉,要特別注意這點(diǎn)爪飘。

5.異常以及try-catch-finally

異常分為兩類:Error和Exception,都繼承自Throwable類

Error:錯(cuò)誤也可以像Exception一樣進(jìn)行拋出和捕獲拉背,只是不推薦

Exception:

checked exception和runtime exception

檢查異常:最常見有IO異常和SQL異常师崎,編譯器不會(huì)通過,會(huì)強(qiáng)制去捕獲椅棺,可trycatch犁罩、可拋出

運(yùn)行異常:NullPotinterException、ArrayIndexOutBoundsException两疚、ArrayStoreException床估、ArithmeticException,這些異常即使有throw操作诱渤,編譯器也會(huì)忽略丐巫。

多線程時(shí),出現(xiàn)異常只是線程退出勺美,程序不會(huì)結(jié)束

?try語句在返回前递胧,將其他所有的操作執(zhí)行完,保留好要返回的值赡茸,而后轉(zhuǎn)入執(zhí)行finally中的語句缎脾,而后分為以下三種情況

情況一:如果finally中有return語句,則會(huì)將try中的return語句”覆蓋“掉坛掠,直接執(zhí)行finally中的return語句赊锚,得到返回值,這樣便無法得到try之前保留好的返回值屉栓。

情況二:如果finally中沒有return語句舷蒲,也沒有改變要返回值,則執(zhí)行完finally中的語句后友多,會(huì)接著執(zhí)行try中的return語句牲平,返回之前保留的值。

情況三:如果finally中沒有return語句域滥,但是改變了要返回的值纵柿,這里有點(diǎn)類似與引用傳遞和值傳遞的區(qū)別蜈抓,分以下兩種情況:1)如果return的數(shù)據(jù)是基本數(shù)據(jù)類型或文本字符串,則在finally中對該基本數(shù)據(jù)的改變不起作用昂儒,try中的return語句依然會(huì)返回進(jìn)入finally塊之前保留的值沟使。2)如果return的數(shù)據(jù)是引用數(shù)據(jù)類型,而在finally中對該引用數(shù)據(jù)類型的屬性值的改變起作用渊跋,try中的return語句返回的就是在finally中改變后的該屬性的值腊嗡。

6.java引用

Java四種引用:

1. 強(qiáng)引用

是指創(chuàng)建一個(gè)對象并把這個(gè)對象賦給一個(gè)引用變量。

比如:

Object object =new?Object();

String str ="hello";

強(qiáng)引用有引用變量指向時(shí)永遠(yuǎn)不會(huì)被垃圾回收拾酝,JVM寧愿拋出OutOfMemory錯(cuò)誤也不會(huì)回收這種對象燕少。

2. 軟引用(SoftReference)

如果一個(gè)對象具有軟引用,內(nèi)存空間足夠蒿囤,垃圾回收器就不會(huì)回收它客们;

如果內(nèi)存空間不足了,就會(huì)回收這些對象的內(nèi)存材诽。只要垃圾回收器沒有回收它底挫,該對象就可以被程序使用。

軟引用可用來實(shí)現(xiàn)內(nèi)存敏感的高速緩存,比如網(wǎng)頁緩存岳守、圖片緩存等凄敢。使用軟引用能防止內(nèi)存泄露,增強(qiáng)程序的健壯性湿痢。

3. 虛引用涝缝,弱引用

無論內(nèi)存是否充足,都會(huì)回收被弱引用關(guān)聯(lián)的對象譬重。

7.程序初始化順序

變量大于塊拒逮、靜態(tài)大于非靜態(tài)!

靜態(tài)對象(變量)由于非靜態(tài)對象(變量)初始化臀规。其中靜態(tài)對象(變量)只初始化一次滩援,而非靜態(tài)對象(變量)可能會(huì)初始化很多次

父類優(yōu)先于子類進(jìn)行初始化

按照成員變量的定義順序進(jìn)行初始化。即使變量定義散布于方法之中塔嬉,他們依然在任何方法(包括構(gòu)造函數(shù))被調(diào)用前先初始化

8.自動(dòng)轉(zhuǎn)型

自動(dòng)轉(zhuǎn)型byte

byte玩徊、short、char在運(yùn)算時(shí)會(huì)轉(zhuǎn)換成int谨究,結(jié)果也是int恩袱。所以short s1=1;s1=s1+1;會(huì)報(bào)錯(cuò)。應(yīng)該為s1=(short)s1+1;

9.重寫和重載

重寫:

子類覆蓋方法必須和父類有相同的函數(shù)名和參數(shù)

返回值必須相同

拋出異常必須必須比父類異常范圍小

子類方法訪問權(quán)限必須比父類大

重載:

重載通過不同的方法參數(shù)來區(qū)分的:不同的參數(shù)個(gè)數(shù)胶哲、不同的參數(shù)類型畔塔、不同的參數(shù)順序

不能通過方法的訪問權(quán)限、返回值類型和拋出的異常類型來進(jìn)行重載

10.面向?qū)ο笕筇卣鳌⑽宕笤瓌t

三大特征:

封裝澈吨,將客觀事物抽象成類把敢,提供可供外部訪問的操作,對內(nèi)部數(shù)據(jù)進(jìn)行了不同級別的保護(hù)谅辣。

繼承:類繼承和接口繼承

多態(tài):重寫修赞、運(yùn)行時(shí)多態(tài),重載桑阶、編譯時(shí)多態(tài)

五大原則:

單一職責(zé)原則:一個(gè)類應(yīng)該僅有一個(gè)引起他變化的原因

開放封閉原則:對擴(kuò)展是開放的榔组,對更改是封閉的

里氏變換原則:子類可以替換父類并且出現(xiàn)在父類能夠出現(xiàn)的任何地方

依賴倒置原則:高層模塊不要依賴底層模塊

接口隔離原則:使用多個(gè)專門的接口比使用單個(gè)接口要好的多

11.線程池

Java通過Executors提供了四種線程池,這四種線程池都是直接或間接配置ThreadPoolExecutor的參數(shù)實(shí)現(xiàn)的:

1.可緩存線程池:

線程數(shù)無限制

有空閑線程則復(fù)用空閑線程联逻,若無空閑線程則新建線程

一定程序減少頻繁創(chuàng)建/銷毀線程,減少系統(tǒng)開銷

創(chuàng)建方法:ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

public static ExecutorService newCachedThreadPool() {

return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

60L, TimeUnit.SECONDS,

new SynchronousQueue());

}

FixedThreadPool()

定長線程池:

可控制線程最大并發(fā)數(shù)(同時(shí)執(zhí)行的線程數(shù))

超出的線程會(huì)在隊(duì)列中等待

創(chuàng)建方法:

//nThreads => 最大線程數(shù)即maximumPoolSize

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads);

//threadFactory => 創(chuàng)建線程的方法检痰,這就是我叫你別理他的那個(gè)星期六包归!你還看!

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads, ThreadFactory threadFactory);

源碼:

public static ExecutorService newFixedThreadPool(int nThreads) {

return new ThreadPoolExecutor(nThreads, nThreads,

0L, TimeUnit.MILLISECONDS,

new LinkedBlockingQueue());

}

ScheduledThreadPool()

定時(shí)線程池:

支持定時(shí)及周期性任務(wù)執(zhí)行铅歼。

創(chuàng)建方法:

//nThreads => 最大線程數(shù)即maximumPoolSize

ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(int corePoolSize);

源碼:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {

return new ScheduledThreadPoolExecutor(corePoolSize);

}

//ScheduledThreadPoolExecutor():

public ScheduledThreadPoolExecutor(int corePoolSize) {

super(corePoolSize, Integer.MAX_VALUE,

DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,

new DelayedWorkQueue());

}

SingleThreadExecutor()

單線程化的線程池:

有且僅有一個(gè)工作線程執(zhí)行任務(wù)

所有任務(wù)按照指定順序執(zhí)行公壤,即遵循隊(duì)列的入隊(duì)出隊(duì)規(guī)則

創(chuàng)建方法:

ExecutorService singleThreadPool = Executors.newSingleThreadPool();

源碼:

public static ExecutorService newSingleThreadExecutor() {

return new FinalizableDelegatedExecutorService

(new ThreadPoolExecutor(1, 1,

0L, TimeUnit.MILLISECONDS,

new LinkedBlockingQueue()));

}

當(dāng)一個(gè)任務(wù)被添加進(jìn)線程池時(shí):

線程數(shù)量未達(dá)到corePoolSize,則新建一個(gè)線程(核心線程)執(zhí)行任務(wù)

線程數(shù)量達(dá)到了corePools椎椰,則將任務(wù)移入隊(duì)列等待

隊(duì)列已滿厦幅,新建線程(非核心線程)執(zhí)行任務(wù)

隊(duì)列已滿,總線程數(shù)又達(dá)到了maximumPoolSize慨飘,就會(huì)由RejectedExecutionHandler拋出異常

12.訪問網(wǎng)頁的過程

輸入地址->瀏覽器查找域名的 IP 地址->瀏覽器向 web 服務(wù)器發(fā)送一個(gè) HTTP 請求->服務(wù)器的永久重定向響應(yīng)->瀏覽器跟蹤重定向地址->服務(wù)器處理請求->服務(wù)器返回一個(gè) HTTP 響應(yīng)->瀏覽器顯示 HTML->瀏覽器發(fā)送請求獲取嵌入在 HTML 中的資源->瀏覽器發(fā)送異步請求

DNS查找過程如下:

瀏覽器會(huì)緩存DNS記錄一段時(shí)間确憨,但是操作系統(tǒng)并沒有告訴瀏覽器儲(chǔ)存DNS記錄的時(shí)間,這樣不同瀏覽器會(huì)儲(chǔ)存?zhèn)€自固定的一個(gè)時(shí)間(2分鐘到30分鐘不等)瓤的。如果在瀏覽器緩存里沒有找到需要的記錄休弃,瀏覽器會(huì)做一個(gè)系統(tǒng)調(diào)用(windows里是gethostbyname),這樣便可獲得系統(tǒng)緩存中的記錄圈膏。接著塔猾,前面的查詢請求發(fā)向路由器,它一般會(huì)有自己的DNS緩存稽坤。接下來要檢查的就是ISP緩存DNS的服務(wù)器丈甸。在這一般都能找到相應(yīng)的緩存記錄。ISP的DNS服務(wù)器從跟域名服務(wù)器開始進(jìn)行遞歸搜索尿褪,從.com頂級域名服務(wù)器到example的域名服務(wù)器睦擂。一般DNS服務(wù)器的緩存中會(huì)有.com域名服務(wù)器中的域名,所以到頂級服務(wù)器的匹配過程不是那么必要了茫多。

HTTP請求的建立過程

建立TCP連接:在HTTP工作開始之前祈匙,Web瀏覽器首先要通過網(wǎng)絡(luò)與Web服務(wù)器建立連接,該連接是通過TCP來完成的,該協(xié)議與IP協(xié)議共同構(gòu)建Internet夺欲,即著名的TCP/IP協(xié)議族跪帝,因此Internet又被稱作是TCP/IP網(wǎng)絡(luò)。HTTP是比TCP更高層次的應(yīng)用層協(xié)議些阅,根據(jù)規(guī)則伞剑,只有低層協(xié)議建立之后才能,才能進(jìn)行更層協(xié)議的連接市埋,因此黎泣,首先要建立TCP連接,一般TCP連接的端口號是80缤谎。在TCP/IP協(xié)議中抒倚,TCP協(xié)議提供可靠的連接服務(wù),采用三次握手建立一個(gè)連接坷澡。

第一次握手:主機(jī)A發(fā)送位碼為syn=1,隨機(jī)產(chǎn)生seq number=1234567的數(shù)據(jù)包到服務(wù)器托呕,主機(jī)B由SYN=1知道,A要求建立聯(lián)機(jī)频敛;

第二次握手:主機(jī)B收到請求后要確認(rèn)聯(lián)機(jī)信息项郊,向A發(fā)送ack number=(主機(jī)A的seq+1),syn=1,ack=1,隨機(jī)產(chǎn)生seq=7654321的包

第三次握手:主機(jī)A收到后檢查ack number是否正確,即第一次發(fā)送的seq number+1,以及位碼ack是否為1斟赚,若正確着降,主機(jī)A會(huì)再發(fā)送ack number=(主機(jī)B的seq+1),ack=1,主機(jī)B收到后確認(rèn)seq值與ack=1則連接建立成功拗军。

完成三次握手任洞,主機(jī)A與主機(jī)B開始傳送數(shù)據(jù)。

一旦建立了TCP連接食绿,Web瀏覽器就會(huì)向Web服務(wù)器發(fā)送請求命令侈咕。

瀏覽器發(fā)送其請求命令之后,還要以頭信息的形式向Web服務(wù)器發(fā)送一些別的信息器紧,之后瀏覽器發(fā)送了一空白行來通知服務(wù)器耀销,它已經(jīng)結(jié)束了該頭信息的發(fā)送。

13SpringMVC

自定義注解自己實(shí)現(xiàn)SpringMVC:DispatcherServlet--->HttpServlet

1.init():scannerPackage--foundBeanInstance--SpringIOC---HanglerMapping

2.service():doPost(),doGet().Path--method--controller--反射執(zhí)行

3.destroy().

以下組件通常使用框架提供實(shí)現(xiàn):

1.DisPatcherServlet:前端控制器(不需要程序員開發(fā))

用戶請求到達(dá)前端控制器铲汪,它相當(dāng)于MVC模式中的C(Controller)熊尉,DispatcherServlet是整個(gè)流程控制的中心,由它調(diào)用其它組件處理用戶的請求掌腰,DispatcherServlet的存在降低了組件之間的耦合性狰住。

作用:作為接受請求,響應(yīng)結(jié)果齿梁,相當(dāng)于轉(zhuǎn)發(fā)器催植,中央處理器肮蛹,減少其他組件之間的耦合度。

2.HandlerMapping:處理器映射器(不需要程序員開發(fā))

HandlerMapping負(fù)責(zé)根據(jù)用戶請求找到Handler(即:處理器)创南,SpringMVC提供了不同的映射器實(shí)現(xiàn)實(shí)現(xiàn)不同的映射方式伦忠,例如:配置文件方式、實(shí)現(xiàn)接口方式稿辙、注解方式等昆码。

作用:根據(jù)請求的Url 查找Handler

3.HandLer:處理器(需要程序員開發(fā))

Handler是繼DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下邻储,Handler對具體的用戶請求進(jìn)行處理赋咽。

由于Handler設(shè)計(jì)到具體的用戶業(yè)務(wù)請求,所以一般情況需要程序員根據(jù)業(yè)務(wù)需求開發(fā)Handler吨娜。

注意:編寫Handler時(shí)按照HandlerAdpter的要求去做脓匿,這樣才可以去正確執(zhí)行Handler。

4.HandlerAdapter:處理器適配器

通過HandlerAdapter對處理器進(jìn)行執(zhí)行宦赠,這是適配器模式的應(yīng)用亦镶,通過擴(kuò)展適配器可以對更多類型的處理器進(jìn)行執(zhí)行。

作用:按照特定的規(guī)則(HandlerAdapter要求的規(guī)則)去執(zhí)行Handler

5.ViewResolver:視圖解析器(不需要程序員開發(fā))ModelAndView邏輯視圖和模型數(shù)據(jù)(邏輯視圖解析成真實(shí)視圖袱瓮,模型數(shù)據(jù)進(jìn)行render)

ViewResolver負(fù)責(zé)將處理結(jié)果生成View視圖,ViewResolver首先根據(jù)邏輯視圖名解析成物理視圖名爱咬,即具體的頁面地址尺借,再生成View視圖對象,最后對View進(jìn)行渲染將處理結(jié)果通過頁面的展示給用戶精拟。SpringMVC框架提供了很多View視圖類型燎斩,包括:JSTLView、freemarkerView蜂绎、pdfView等等.

作用:進(jìn)行視圖解析栅表,根據(jù)邏輯視圖名解析成真正的視圖(view)。

6.View視圖(需要程序員開發(fā) jsp)

View是一個(gè)接口师枣,實(shí)現(xiàn)類支持不同的View類型(jsp怪瓶、freemarker、pdf)

一般情況下需要通過頁面標(biāo)簽或者頁面模板技術(shù)將模型數(shù)據(jù)通過頁面展示給用戶践美,需要由程序員根據(jù)業(yè)務(wù)需求開發(fā)具體的頁面洗贰。

【流程圖說明】


具體步驟:

首先用戶發(fā)送請求——>DispatcherServlet,前端控制器收到請求后自己不進(jìn)行處理陨倡,而是委托給其他的解析器進(jìn)行處理敛滋,作為統(tǒng)一訪問點(diǎn),進(jìn)行全局的流程控制兴革;

DispatcherServlet——>HandlerMapping绎晃,HandlerMapping 將會(huì)把請求映射為 HandlerExecutionChain 對象(包含一個(gè) Handler 處理器(頁面控制器)對象蜜唾、多個(gè) HandlerInterceptor 攔截器)對象,通過這種策略模式庶艾,很容易添加新的映射策略袁余;

DispatcherServlet——>HandlerAdapter,HandlerAdapter 將會(huì)把處理器包裝為適配器落竹,從而支持多種類型的處理器泌霍,即適配器設(shè)計(jì)模式的應(yīng)用,從而很容易支持很多類型的處理器述召;

HandlerAdapter——>處理器功能處理方法的調(diào)用朱转,HandlerAdapter 將會(huì)根據(jù)適配的結(jié)果調(diào)用真正的處理器的功能處理方法,完成功能處理积暖;并返回一個(gè) ModelAndView 對象(包含模型數(shù)據(jù)藤为、邏輯視圖名);

ModelAndView 的邏輯視圖名——> ViewResolver夺刑, ViewResolver 將把邏輯視圖名解析為具體的 View缅疟,通過這種策略模式,很容易更換其他視圖技術(shù)遍愿;

View——>渲染存淫,View 會(huì)根據(jù)傳進(jìn)來的 Model 模型數(shù)據(jù)進(jìn)行渲染,此處的 Model 實(shí)際是一個(gè) Map 數(shù)據(jù)結(jié)構(gòu)沼填,因此很容易支持其他視圖技術(shù)桅咆;

返回控制權(quán)給 DispatcherServlet,由 DispatcherServlet 返回響應(yīng)給用戶坞笙,到此一個(gè)流程結(jié)束岩饼。

14 Sevlet

Servlet生命周期(單例多線程):

servlet:servlet是一種運(yùn)行服務(wù)器端的java應(yīng)用程序,具有獨(dú)立于平臺和協(xié)議的特性薛夜,并且可以動(dòng)態(tài)的生成web頁面籍茧,它工作在客戶端請求與服務(wù)器響應(yīng)的中間層。最早支持 Servlet 技術(shù)的是 JavaSoft 的 Java Web Server梯澜。此后寞冯,一些其它的基于 Java 的 Web Server 開始支持標(biāo)準(zhǔn)的 Servlet API。Servlet 的主要功能在于交互式地瀏覽和修改數(shù)據(jù)晚伙,生成動(dòng)態(tài) Web 內(nèi)容简十。這個(gè)過程為:

1) 客戶端發(fā)送請求至服務(wù)器端;

2) 服務(wù)器將請求信息發(fā)送至 Servlet撬腾;

3) Servlet 生成響應(yīng)內(nèi)容并將其傳給服務(wù)器螟蝙。響應(yīng)內(nèi)容動(dòng)態(tài)生成,通常取決于客戶端的請求民傻;

4) 服務(wù)器將響應(yīng)返回給客戶端胰默。

在 Web 應(yīng)用程序中场斑,一個(gè) Servlet 在一個(gè)時(shí)刻可能被多個(gè)用戶同時(shí)訪問。這時(shí) Web 容器將為每個(gè)用戶創(chuàng)建一個(gè)線程來執(zhí)行 Servlet牵署。如果 Servlet 不涉及共享資源的問題漏隐,不必關(guān)心多線程問題。但如果 Servlet 需要共享資源奴迅,需要保證 Servlet 是線程安全的青责。

最新版本3.1,為了簡化開發(fā)流程取具,Servlet 3.0 引入了注解(annotation)脖隶,這使得 web 部署描述符 web.xml 不再是必須的選擇。

Servlet 生命周期可被定義為從創(chuàng)建直到毀滅的整個(gè)過程暇检。以下是 Servlet 遵循的過程:

加載产阱,加載Servlet類

創(chuàng)建,通過構(gòu)造函數(shù)創(chuàng)建一個(gè)Servlet實(shí)例

Servlet 通過調(diào)用init ()方法進(jìn)行初始化块仆。

Servlet 調(diào)用service()方法來處理客戶端的請求构蹬。

Servlet 通過調(diào)用destroy()方法終止(結(jié)束)。

最后悔据,Servlet 是由 JVM 的垃圾回收器進(jìn)行垃圾回收的庄敛。

init() 方法

init 方法被設(shè)計(jì)成只調(diào)用一次。它在第一次創(chuàng)建 Servlet 時(shí)被調(diào)用科汗,在后續(xù)每次用戶請求時(shí)不再調(diào)用铐姚。因此,它是用于一次性初始化肛捍,就像 Applet 的 init 方法一樣。

service() 方法

service() 方法是執(zhí)行實(shí)際任務(wù)的主要方法之众。Servlet 容器(即 Web 服務(wù)器)調(diào)用 service() 方法來處理來自客戶端(瀏覽器)的請求拙毫,并把格式化的響應(yīng)寫回給客戶端。

destroy() 方法

destroy() 方法只會(huì)被調(diào)用一次棺禾,在 Servlet 生命周期結(jié)束時(shí)被調(diào)用缀蹄。destroy() 方法可以讓您的 Servlet 關(guān)閉數(shù)據(jù)庫連接、停止后臺線程膘婶、把 Cookie 列表或點(diǎn)擊計(jì)數(shù)器寫入到磁盤缺前,并執(zhí)行其他類似的清理活動(dòng)。

在調(diào)用 destroy() 方法之后悬襟,servlet 對象被標(biāo)記為垃圾回收衅码。

Servlet的調(diào)用過程

1.客戶端通過發(fā)送請求給Tomcat,Tomcat發(fā)送客戶端的請求頁面給客戶端脊岳。

2.用戶對請求頁面進(jìn)行相關(guān)操作后將頁面提交給Tomcat,Tomcat將其封裝成一個(gè)HttpRequest對象逝段,然后對請求進(jìn)行處理,垛玻。

3.Tomcat截獲請求,根據(jù)action屬性值查詢xml文件中對應(yīng)的servlet-name奶躯,再根據(jù)servlet-name查詢到對應(yīng)的java類(如果是第一次帚桩,Tomcat則會(huì)將servlet編譯成java類文件,所以如果servlet有很多的話第一次運(yùn)行的時(shí)候程序會(huì)比較慢)嘹黔。

4.Tomcat實(shí)例化查詢到的java類账嚎,注意該類只實(shí)例化一次。

5.調(diào)用java類對象的service()方法(如果不對service()方法進(jìn)行重寫則根據(jù)提交的方式來決定執(zhí)行doPost()方法還是doGet()方法)儡蔓。

6.通過request對象取得客戶端傳過來的數(shù)據(jù)郭蕉,對數(shù)據(jù)進(jìn)行處理后通過response對象將處理結(jié)果寫回客戶端。

15 Object方法

Object是所有類的父類浙值,任何類都默認(rèn)繼承Object恳不。

clone:保護(hù)方法,實(shí)現(xiàn)對象的淺復(fù)制开呐,只有實(shí)現(xiàn)了Cloneable接口才可以調(diào)用該方法烟勋,否則拋出CloneNotSupportedException異常。淺復(fù)制

equals:在Object中與==是一樣的筐付,子類一般需要重寫該方法

hashCode:該方法用于哈希查找卵惦,重寫了equals方法一般都要重寫hashCode方法。這個(gè)方法在一些具有哈希功能的Collection中用到

getClass:final方法瓦戚,獲得運(yùn)行時(shí)類型

wait:使當(dāng)前線程等待該對象的鎖沮尿,當(dāng)前線程必須是該對象的擁有者,也就是具有該對象的鎖较解。wait()方法一直等待畜疾,直到獲得鎖或者被中斷。wait(long?timeout)設(shè)定一個(gè)超時(shí)間隔印衔,如果在規(guī)定時(shí)間內(nèi)沒有獲得鎖就返回啡捶。

調(diào)用該方法后當(dāng)前線程進(jìn)入睡眠狀態(tài),直到以下事件發(fā)生:

1.其他線程調(diào)用了該對象的notify方法

2.其他線程調(diào)用了該對象的notifyAll方法

3.其他線程調(diào)用了interrupt中斷該線程

4.時(shí)間間隔到了

此時(shí)該線程就可以被調(diào)度了奸焙,如果是被中斷的話就拋出一個(gè)InterruptedException異常

notify:喚醒在該對象上等待的某個(gè)線程

notifyAll:喚醒在該對象上等待的所有線程

toString:轉(zhuǎn)換成字符串瞎暑,一般子類都有重寫,否則打印句柄

16?Intercepter和filter与帆、Interceptor

filter:filter是一個(gè)可以復(fù)用的代碼片段了赌,可以用來轉(zhuǎn)換HTTP請求、響應(yīng)和頭信息玄糟。Filter不像Servlet勿她,它不能產(chǎn)生一個(gè)請求或者響應(yīng),它只是修改對某一資源的請求阵翎,或者修改從某一的響應(yīng)嫂拴。Servlet中的過濾器Filter是實(shí)現(xiàn)了javax.servlet.Filter接口的服務(wù)器端程序播揪,主要的用途是過濾字符編碼、做一些業(yè)務(wù)邏輯判斷等筒狠。其工作原理是猪狈,只要你在web.xml文件配置好要攔截的客戶端請求,它都會(huì)幫你攔截到請求辩恼,此時(shí)你就可以對請求或響應(yīng)(Request雇庙、Response)統(tǒng)一設(shè)置編碼,簡化操作灶伊;同時(shí)還可進(jìn)行邏輯判斷疆前,如用戶是否已經(jīng)登陸、有沒有權(quán)限訪問該頁面等等工作聘萨。它是隨你的web應(yīng)用啟動(dòng)而啟動(dòng)的竹椒,只初始化一次,以后就可以攔截相關(guān)請求米辐,只有當(dāng)你的web應(yīng)用停止或重新部署的時(shí)候才銷毀胸完。Filter可認(rèn)為是Servlet的一種“變種”,它主要用于對用戶請求進(jìn)行預(yù)處理翘贮,也可以對HttpServletResponse進(jìn)行后處理赊窥,是個(gè)典型的處理鏈。它與Servlet的區(qū)別在于:它不能直接向用戶生成響應(yīng)狸页。完整的流程是:Filter對用戶請求進(jìn)行預(yù)處理锨能,接著將請求交給Servlet進(jìn)行處理并生成響應(yīng),最后Filter再對服務(wù)器響應(yīng)進(jìn)行后處理芍耘。

Filter有如下幾個(gè)用處址遇。

在HttpServletRequest到達(dá)Servlet之前,攔截客戶的HttpServletRequest斋竞。

根據(jù)需要檢查HttpServletRequest倔约,也可以修改HttpServletRequest頭和數(shù)據(jù)。

在HttpServletResponse到達(dá)客戶端之前窃页,攔截HttpServletResponse。

根據(jù)需要檢查HttpServletResponse复濒,也可以修改HttpServletResponse頭和數(shù)據(jù)脖卖。

Filter有如下幾個(gè)種類。

用戶授權(quán)的Filter:Filter負(fù)責(zé)檢查用戶請求巧颈,根據(jù)請求過濾用戶非法請求畦木。

日志Filter:詳細(xì)記錄某些特殊的用戶請求。

負(fù)責(zé)解碼的Filter:包括對非標(biāo)準(zhǔn)編碼的請求解碼砸泛。

能改變XML內(nèi)容的XSLT Filter等十籍。

Filter可負(fù)責(zé)攔截多個(gè)請求或響應(yīng)蛆封;一個(gè)請求或響應(yīng)也可被多個(gè)請求攔截。

創(chuàng)建一個(gè)Filter只需兩個(gè)步驟:

建Filter處理類勾栗;

web.xml文件中配置Filter惨篱。

listener:監(jiān)聽器,從字面上可以看出listener主要用來監(jiān)聽只用围俘。通過listener可以監(jiān)聽web服務(wù)器中某一個(gè)執(zhí)行動(dòng)作砸讳,并根據(jù)其要求作出相應(yīng)的響應(yīng)。通俗的語言說就是在application界牡,session簿寂,request三個(gè)對象創(chuàng)建消亡或者往其中添加修改刪除屬性時(shí)自動(dòng)執(zhí)行代碼的功能組件。比如spring 的總監(jiān)聽器 會(huì)在服務(wù)器啟動(dòng)的時(shí)候?qū)嵗覀兣渲玫腷ean對象 宿亡、 hibernate 的 session 的監(jiān)聽器會(huì)監(jiān)聽session的活動(dòng)和生命周期常遂,負(fù)責(zé)創(chuàng)建,關(guān)閉session等活動(dòng)挽荠。

Servlet的監(jiān)聽器Listener克胳,它是實(shí)現(xiàn)了javax.servlet.ServletContextListener 接口的服務(wù)器端程序,它也是隨web應(yīng)用的啟動(dòng)而啟動(dòng)坤按,只初始化一次毯欣,隨web應(yīng)用的停止而銷毀。主要作用是: 做一些初始化的內(nèi)容添加工作臭脓、設(shè)置一些基本的內(nèi)容酗钞、比如一些參數(shù)或者是一些固定的對象等等。

interceptor:是在面向切面編程的来累,就是在你的service或者一個(gè)方法砚作,前調(diào)用一個(gè)方法,或者在方法后調(diào)用一個(gè)方法嘹锁,是基于JAVA的反射機(jī)制葫录。比如動(dòng)態(tài)代理就是攔截器的簡單實(shí)現(xiàn),在你調(diào)用方法前打印出字符串(或者做其它業(yè)務(wù)邏輯的操作)领猾,也可以在你調(diào)用方法后打印出字符串米同,甚至在你拋出異常的時(shí)候做業(yè)務(wù)邏輯的操作。

servlet摔竿、filter面粮、listener是配置到web.xml中(web.xml 的加載順序是:context-param -> listener -> filter -> servlet),interceptor不配置到web.xml中继低,struts的攔截器配置到struts.xml中熬苍。spring的攔截器配置到spring.xml中。

二、生命周期:

1柴底、servlet:一般繼承HttpServlet(一般的婿脸,通用Servlet由javax.servlet.GenericServlet實(shí)現(xiàn)Servlet接口。程序設(shè)計(jì)人員可以通過使用或繼承這個(gè)類來實(shí)現(xiàn)通用Servlet應(yīng)用柄驻。javax.servlet.http.HttpServlet實(shí)現(xiàn)了專門用于響應(yīng)HTTP請求的Servlet狐树,提供了響應(yīng)對應(yīng)HTTP標(biāo)準(zhǔn)請求的doGet()、doPost()等方法)凿歼,web.xml配置servlet時(shí)如果加上load-on-start(在servlet的配置當(dāng)中褪迟,1的含義是:標(biāo)記容器是否在啟動(dòng)的時(shí)候就加載這個(gè)servlet。當(dāng)值為0或者大于0時(shí)答憔,表示容器在應(yīng)用啟動(dòng)時(shí)就加載這個(gè)servlet味赃;當(dāng)是一個(gè)負(fù)數(shù)時(shí)或者沒有指定時(shí),則指示容器在該servlet被選擇時(shí)才加載虐拓。正數(shù)的值越小心俗,啟動(dòng)該servlet的優(yōu)先級越高。)為1時(shí)候蓉驹,Web應(yīng)用啟動(dòng)時(shí)候加載Servlet城榛。當(dāng)servlet被部署在應(yīng)用服務(wù)器中(應(yīng)用服務(wù)器中用于管理Java組件的部分被抽象成為容器)以后,由容器控制servlet的生命周期态兴。除非特殊指定狠持,否則在容器啟動(dòng)的時(shí)候,servlet是不會(huì)被加載的瞻润,servlet只會(huì)在第一次請求的時(shí)候被加載和實(shí)例化喘垂。servlet一旦被加載,一般不會(huì)從容器中刪除绍撞,直至應(yīng)用服務(wù)器關(guān)閉或重新啟動(dòng)正勒。但當(dāng)容器做內(nèi)存回收動(dòng)作時(shí),servlet有可能被刪除傻铣。也正是因?yàn)檫@個(gè)原因章贞,第一次訪問servlet所用的時(shí)間要大大多于以后訪問所用的時(shí)間。servlet在服務(wù)器的運(yùn)行生命周期為非洲,在第一次請求(或其實(shí)體被內(nèi)存垃圾回收后再被訪問)時(shí)被加載并執(zhí)行一次初始化方法鸭限,跟著執(zhí)行正式運(yùn)行方法箫老,之后會(huì)被常駐并每次被請求時(shí)直接執(zhí)行正式運(yùn)行方法铜异,直到服務(wù)器關(guān)閉或被清理時(shí)執(zhí)行一次銷毀方法后實(shí)體銷毀。Java服務(wù)器頁面(JSP)是HttpServlet的擴(kuò)展烹骨。由于HttpServlet大多是用來響應(yīng)HTTP請求缆瓣,并返回Web頁面(例如HTML喧枷、XML)虹统,所以不可避免地弓坞,在編寫servlet時(shí)會(huì)涉及大量的HTML內(nèi)容隧甚,這給servlet的書寫效率和可讀性帶來很大障礙,JSP便是在這個(gè)基礎(chǔ)上產(chǎn)生的渡冻。其功能是使用HTML的書寫格式戚扳,在適當(dāng)?shù)牡胤郊尤隞ava代碼片斷,將程序員從復(fù)雜的HTML中解放出來族吻,更專注于servlet本身的內(nèi)容帽借。JSP在首次被訪問的時(shí)候被應(yīng)用服務(wù)器轉(zhuǎn)換為servlet,在以后的運(yùn)行中超歌,容器直接調(diào)用這個(gè)servlet砍艾,而不再訪問JSP頁面。JSP的實(shí)質(zhì)仍然是servlet巍举。

(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(),destory(),doFilter()荐虐,空實(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í)例。

3汽烦、listener:Servlet的監(jiān)聽器Listener涛菠,它是實(shí)現(xiàn)了javax.servlet.ServletContextListener 接口的服務(wù)器端程序,它也是隨web應(yīng)用的啟動(dòng)而啟動(dòng),只初始化一次俗冻,隨web應(yīng)用的停止而銷毀礁叔。

web.xml?的加載順序是:context- param?->?listener?->?filter?->?servlet

4、interceptor:以struts的攔截器為例迄薄,加載了struts.xml以后琅关,初始化相應(yīng)攔截器。當(dāng)action請求來時(shí)調(diào)用intercept方法讥蔽,服務(wù)器停止銷毀interceptor涣易。

三、職責(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í)行

3顷级、listener:職責(zé)如概念凫乖。

servlet2.4規(guī)范中提供了8個(gè)listener接口弓颈,可以將其分為三類翔冀,分別如下:

第一類:與servletContext有關(guān)的listner接口纤子。包括:ServletContextListener款票、ServletContextAttributeListener

第二類:與HttpSession有關(guān)的Listner接口徽职。包括:HttpSessionListner、HttpSessionAttributeListener说订、HttpSessionBindingListener陶冷、 ? ? ? ? ? ? ? ? ? ? ?HttpSessionActivationListener埂伦;

第三類:與ServletRequest有關(guān)的Listener接口,包括:ServletRequestListner膊毁、ServletRequestAttributeListener

4基跑、interceptor:與過濾器十分相似媳否,通過層層攔截篱竭,處理用戶的請求和響應(yīng)掺逼。

四吕喘、幾個(gè)區(qū)別:

1,servlet 流程是短的,url傳來之后漓概,就對其進(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)行字符編碼的過濾派诬,檢測用戶是否登陸的過濾默赂,禁止頁面緩存等

3, servlet,filter都是針對url之類的缆八,而listener是針對對象的操作的,如session的創(chuàng)建栏妖,session.setAttribute的發(fā)生吊趾,在這樣的事件發(fā)生時(shí)做一些事情论泛。

可用來進(jìn)行:Spring整合Struts,為Struts的action注入屬性,web應(yīng)用定時(shí)任務(wù)的實(shí)現(xiàn)蜡峰,在線人數(shù)的統(tǒng)計(jì)等

4湿颅,interceptor 攔截器油航,類似于filter,不過在struts.xml中配置谊囚,不是在web.xml,并且不是針對URL的镰踏,而是針對action,當(dāng)頁面提交action時(shí)奠伪,進(jìn)行過濾操作绊率,相當(dāng)于struts1.x提供的plug-in機(jī)制滤否,可以看作顽聂,前者是struts1.x自帶的filter,而interceptor 是struts2 提供的filter.

與filter不同點(diǎn):(1)不在web.xml中配置紊搪,而是在struts.xml中完成配置耀石,與action在一起

( 2? ) 可由action自己指定用哪個(gè)interceptor 來在接收之前做事

5,struts2中的過濾器和攔截器的區(qū)別與聯(lián)系:

(1)揭鳞、攔截器是基于java反射機(jī)制的,而過濾器是基于函數(shù)回調(diào)的乓梨。

(2)扶镀、過濾器依賴與servlet容器焰轻,而攔截器不依賴與servlet容器辱志。

(3)揩懒、攔截器只能對Action請求起作用旭从,而過濾器則可以對幾乎所有請求起作用和悦。

(4)鸽素、攔截器可以訪問Action上下文馍忽、值棧里的對象,而過濾器不能徒探。

(5)、在Action的生命周期中磨澡,攔截器可以多次調(diào)用,而過濾器只能在容器初始化時(shí)被調(diào)用一次稚字。


17 .HashMap && ConcurrentHashMap

HashMap:先說HashMap胆描,HashMap是線程不安全的袄友,在并發(fā)環(huán)境下,可能會(huì)形成環(huán)狀鏈表(擴(kuò)容時(shí)可能造成)旋廷,導(dǎo)致get操作時(shí)饶碘,cpu空轉(zhuǎn)扎运,所以豪治,在并發(fā)環(huán)境中使用HashMap是非常危險(xiǎn)的负拟。

HashTable: HashTable和HashMap的實(shí)現(xiàn)原理幾乎一樣花吟,差別無非是1.HashTable不允許key和value為null衅澈;2.HashTable是線程安全的矾麻。但是HashTable線程安全的策略實(shí)現(xiàn)代價(jià)卻太大了险耀,簡單粗暴甩牺,get/put所有相關(guān)操作都是synchronized的贬派,這相當(dāng)于給整個(gè)哈希表加了一把大鎖搞乏,多線程訪問時(shí)候请敦,只要有一個(gè)線程訪問或操作該對象侍筛,那其他線程只能阻塞,相當(dāng)于將所有的操作串行化禽笑,在競爭激烈的并發(fā)場景中性能就會(huì)非常差佳镜。

HashTable性能差主要是由于所有操作需要競爭同一把鎖邀杏,而如果容器中有多把鎖望蜡,每一把鎖鎖一段數(shù)據(jù)脖律,這樣在多線程訪問時(shí)不同段的數(shù)據(jù)時(shí)芦疏,就不會(huì)存在鎖競爭了酸茴,這樣便可以有效地提高并發(fā)效率薪捍。這就是ConcurrentHashMap所采用的"分段鎖"思想酪穿。

HashMap Put操作:

在JDK1.7版本中,ConcurrentHashMap的數(shù)據(jù)結(jié)構(gòu)是由一個(gè)Segment數(shù)組和多個(gè)HashEntry組成只磷,如下圖所示:

Segment數(shù)組的意義就是將一個(gè)大的table分割成多個(gè)小的table來進(jìn)行加鎖馋贤,也就是上面的提到的鎖分離技術(shù)配乓,而每一個(gè)Segment元素存儲(chǔ)的是HashEntry數(shù)組+鏈表犹芹,這個(gè)和HashMap的數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)一樣.

Segment的大小ssize默認(rèn)為16,HashEntry最小的容量為2

JDK1.8的實(shí)現(xiàn)

JDK1.8的實(shí)現(xiàn)已經(jīng)摒棄了Segment的概念腰埂,而是直接用Node數(shù)組+鏈表+紅黑樹的數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)翁巍,并發(fā)控制使用Synchronized和CAS來操作,整個(gè)看起來就像是優(yōu)化過且線程安全的HashMap驰凛,雖然在JDK1.8中還能看到Segment的數(shù)據(jù)結(jié)構(gòu)恰响,但是已經(jīng)簡化了屬性渔隶,只是為了兼容舊版本

ConcurrentHashMap中有一個(gè)segments[]數(shù)組:

final Segment[] segments;

Segment如下,繼承了ReetrantLock:

static final class Segment?extends ReentrantLock implementsSerializable {

transient volatile HashEntry[]table;}

segment就是一個(gè)HashMap的結(jié)構(gòu)

static final class HashEntry {

final inthash;

finalKkey;

volatileVvalue;

volatileHashEntrynext;}

18 Redis和Memcached的異同呈野。

Memcached

可以利用多核優(yōu)勢,單實(shí)例吞吐量極高昨悼,可以達(dá)到幾十萬QPS率触;

只支持簡單的key/value數(shù)據(jù)結(jié)構(gòu)葱蝗,不像Redis可以支持豐富的數(shù)據(jù)類型。

無法進(jìn)行持久化悼凑,數(shù)據(jù)不能備份户辫,只能用于緩存使用寸莫,且重啟后數(shù)據(jù)全部丟失桃纯。

無法進(jìn)行數(shù)據(jù)同步态坦,不能將MC中的數(shù)據(jù)遷移到其他MC實(shí)例中。

Memcached內(nèi)存分配采用Slab Allocation機(jī)制管理內(nèi)存谜诫,value大小分布差異較大時(shí)會(huì)造成內(nèi)存利用率降低喻旷, 并引發(fā)低利用率時(shí)依然出現(xiàn)踢出等問題且预。需要用戶注重value設(shè)計(jì)。

Redis

支持多種數(shù)據(jù)結(jié)構(gòu)涮拗,如string多搀、 list惯退、hash、set锁蠕、zset等夷野;

支持持久化操作,可以進(jìn)行aof及rdb數(shù)據(jù)持久化到磁盤荣倾,從而進(jìn)行數(shù)據(jù)備份或數(shù)據(jù)恢復(fù)等操作悯搔,較好的防止數(shù)據(jù)丟失的手段;

支持通過Replication進(jìn)行數(shù)據(jù)復(fù)制舌仍,通過master-slave機(jī)制,可以實(shí)時(shí)進(jìn)行數(shù)據(jù)的同步復(fù)制來實(shí)現(xiàn)HA铸豁;

單線程請求灌曙,所有命令串行執(zhí)行,并發(fā)情況下不需要考慮數(shù)據(jù)一致性問題节芥,但性能受限于CPU性能在刺,故單實(shí)例CPU最高才可能達(dá)到5-6wQPS每秒;

支持pub/sub消息訂閱機(jī)制头镊,可以用來進(jìn)行消息訂閱與通知蚣驼;

Redis在string類型上會(huì)消耗較多內(nèi)存,可以使用hash表壓縮存儲(chǔ)以降低內(nèi)存耗用相艇。

19Redis作為分布式緩存可能會(huì)存在哪些問題隙姿,怎么解決?

緩存穿透預(yù)防及優(yōu)化:緩存穿透是指查詢一個(gè)根本不存在的數(shù)據(jù)厂捞,緩存層和存儲(chǔ)層都不會(huì)命中输玷;緩存穿透將導(dǎo)致不存在的數(shù)據(jù)每次請求都要到存儲(chǔ)層去查詢,失去了緩存保護(hù)后端存儲(chǔ)的意義靡馁;解決方法:緩存空對象和布隆過濾器攔截欲鹏;

緩存雪崩問題優(yōu)化:由于緩存層承載著大量請求,有效的保護(hù)了存儲(chǔ)層臭墨,但是如果緩存層由于某些原因整體不能提供服務(wù)赔嚎,于是所有的請求都會(huì)達(dá)到存儲(chǔ)層,存儲(chǔ)層的調(diào)用量會(huì)暴增胧弛,造成存儲(chǔ)層也會(huì)掛掉的情況尤误;預(yù)防和解決緩存雪崩問題,可以從以下三個(gè)方面進(jìn)行著手:保證緩存層服務(wù)高可用性结缚、依賴隔離組件為后端限流并降級损晤、提前演練。

緩存熱點(diǎn)key重建優(yōu)化:開發(fā)人員使用緩存和過期時(shí)間的策略既可以加速數(shù)據(jù)讀寫红竭,又保證數(shù)據(jù)的定期更新尤勋,這種模式基本能夠滿足絕大部分需求喘落。但如果熱點(diǎn)Key和重建緩存耗時(shí)兩個(gè)問題同時(shí)出現(xiàn),可能就會(huì)對應(yīng)用造成致命的危害最冰;解決方法:互斥鎖(只允許一個(gè)線程重建緩存)瘦棋、永遠(yuǎn)不過期(唯一不足的就是重構(gòu)緩存期間會(huì)出現(xiàn)數(shù)據(jù)不一致的情況)。

20.Mysql

主鍵和索引的區(qū)別:

惟一地標(biāo)識一行暖哨。

作為一個(gè)可以被外鍵有效引用的對象赌朋。

索引是一種特殊的文件(InnoDB數(shù)據(jù)表上的索引是表空間的一個(gè)組成部分),它們包含著對數(shù)據(jù)表里所有記錄的引用指針篇裁。

主鍵索引和唯一索引的區(qū)別:主鍵一定會(huì)創(chuàng)建一個(gè)唯一索引箕慧,但是有唯一索引的列不一定是主鍵;主鍵不允許為空值茴恰,唯一索引列允許空值颠焦;一個(gè)表只能有一個(gè)主鍵,但是可以有多個(gè)唯一索引主鍵可以被其他表引用為外鍵往枣,唯一索引列不可以伐庭;主鍵是一種約束,而唯一索引是一種索引分冈,是表的冗余數(shù)據(jù)結(jié)構(gòu)圾另,兩者有本質(zhì)的差別。

MyISAM和InnoDB索引結(jié)構(gòu)有很大差異雕沉,這里以InnoDB為例集乔,InnoDB的葉節(jié)點(diǎn)存儲(chǔ)的是數(shù)據(jù)的行,而除了主鍵之外的列索引存儲(chǔ)的是主鍵key坡椒,也就是說在查詢的時(shí)候需要二次查詢扰路,先通過列索引找到主鍵,再通過主鍵索引找到row倔叼。

MySql的事務(wù)隔離級別有哪幾種汗唱?

隔離級別用于表述并發(fā)事務(wù)之間的相互干擾程度,其基于鎖機(jī)制進(jìn)行并發(fā)控制丈攒。

可序列化(Serializable):事務(wù)一個(gè)接一個(gè)的執(zhí)行哩罪,完全相互獨(dú)立;實(shí)現(xiàn)可序列化要求在選定對象上的讀鎖和寫鎖保持直到事務(wù)結(jié)束后才能釋放巡验;在SELECT的查詢中使用一個(gè)WHERE子句來描述一個(gè)范圍時(shí)應(yīng)該獲得一個(gè)“范圍鎖”际插。

可重復(fù)度(Repeatable Read):事務(wù)A讀取數(shù)據(jù)之后,對涉及的數(shù)據(jù)加鎖显设,不允許其他事務(wù)進(jìn)行修改框弛,由于其他事務(wù)會(huì)插入新的數(shù)據(jù),因此會(huì)產(chǎn)生幻讀敷硅;對選定對象的讀鎖和寫鎖一直保持到事務(wù)結(jié)束功咒,但不要求“范圍鎖”愉阎,因此可能會(huì)發(fā)生幻讀绞蹦;可重復(fù)讀是MySQL的默認(rèn)事務(wù)隔離級別力奋。

讀取已提交(Read Committed):只能看到其他事務(wù)已經(jīng)提交的數(shù)據(jù),避免了臟讀幽七,但存在不可重復(fù)讀景殷、幻讀;DBMS需要對選定對象的寫鎖(write locks)一直保持到事務(wù)結(jié)束澡屡,但是讀鎖(read locks)在SELECT操作完成后馬上釋放猿挚,且不要求“范圍鎖”。

讀取未提交(Read Uncommitted):可以看到其他事務(wù)沒有提交的數(shù)據(jù)驶鹉,出現(xiàn)臟讀绩蜻、不可重復(fù)讀、幻讀室埋;

[PS補(bǔ)充]

不可重復(fù)讀的重點(diǎn)是修改:同樣的條件办绝,讀取過的數(shù)據(jù),再次讀取出來發(fā)現(xiàn)值不一樣了姚淆。

幻讀的重點(diǎn)在于新增或者刪除:同樣的條件孕蝉,第1次和第2次讀出來的記錄數(shù)不一樣。

MySql的MVVC有什么作用腌逢?

多版本并發(fā)控制(MVCC)降淮,來實(shí)現(xiàn)MySQL上的多事務(wù)并發(fā)訪問時(shí),隔離級別控制搏讶;

數(shù)據(jù)版本:并發(fā)事務(wù)執(zhí)行時(shí)佳鳖,同一行數(shù)據(jù)有多個(gè)版本;

事務(wù)版本:每個(gè)事務(wù)都有一個(gè)事務(wù)版本媒惕;

版本有序:版本是通過時(shí)間來標(biāo)識的腋颠;

通過MVCC實(shí)現(xiàn)的效果是同一時(shí)刻、同一張表吓笙、多個(gè)并發(fā)事務(wù)淑玫,看到的數(shù)據(jù)是不同的。

MVCC本質(zhì)使用了copy-on-write面睛,為每個(gè)數(shù)據(jù)保留多份snapshot絮蒿,不同snapshot之間,使用指針連接成鏈表叁鉴;update操作土涝,能看到的snapshot是受限的,是鏈表上小于等于當(dāng)前事務(wù)版本的最大版本(讀取已提交:離當(dāng)前事務(wù)最近的已提交版本)幌墓;

21.如何設(shè)計(jì)高性能但壮、高并發(fā)冀泻、高可用

系統(tǒng)架構(gòu)三個(gè)利器:RPC服務(wù)組件、消息中間件(交互異步化蜡饵、流量削峰)弹渔、配置管理(灰度發(fā)布、降級)溯祸;

無狀態(tài):接口層最重要的就是無狀態(tài)肢专,將有狀態(tài)的數(shù)據(jù)剝離到數(shù)據(jù)庫或緩存中;

如何改善延時(shí):找關(guān)鍵路徑(“28原則”)焦辅、空間換時(shí)間博杖,如各級緩存;時(shí)間換空間筷登,如傳輸壓縮剃根,解決網(wǎng)絡(luò)傳輸?shù)钠款i;多核并行前方,減少鎖競爭狈醉;更適合的算法和數(shù)據(jù)結(jié)構(gòu);通過性能測試和監(jiān)控找出瓶頸镣丑;減少系統(tǒng)調(diào)用和上下文切換舔糖;

如何提高吞吐量:復(fù)制、擴(kuò)容莺匠、異步化金吗、緩存;

如何保障穩(wěn)定性:提高可用性趣竣、分組和隔離摇庙、限流、降級遥缕、監(jiān)控和故障切換卫袒;

理解高可用系統(tǒng):要做到數(shù)據(jù)不丟,就必需要持久化单匣;要做到服務(wù)高可用夕凝,就必需要有備用(復(fù)本),無論是應(yīng)用結(jié)點(diǎn)還是數(shù)據(jù)結(jié)點(diǎn)户秤;要做到復(fù)制码秉,就會(huì)有數(shù)據(jù)一致性的問題;我們不可能做到100%的高可用鸡号,也就是說转砖,我們能做到幾個(gè)9個(gè)的SLA;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鲸伴,一起剝皮案震驚了整個(gè)濱河市府蔗,隨后出現(xiàn)的幾起案子晋控,更是在濱河造成了極大的恐慌,老刑警劉巖姓赤,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赡译,死亡現(xiàn)場離奇詭異,居然都是意外死亡模捂,警方通過查閱死者的電腦和手機(jī)捶朵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門蜘矢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狂男,“玉大人,你說我怎么就攤上這事品腹♂常” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵舞吭,是天一觀的道長泡垃。 經(jīng)常有香客問我,道長羡鸥,這世上最難降的妖魔是什么蔑穴? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮惧浴,結(jié)果婚禮上存和,老公的妹妹穿的比我還像新娘。我一直安慰自己衷旅,他們只是感情好捐腿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著柿顶,像睡著了一般茄袖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘁锯,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天宪祥,我揣著相機(jī)與錄音,去河邊找鬼家乘。 笑死蝗羊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的烤低。 我是一名探鬼主播肘交,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扑馁!你這毒婦竟也來了涯呻?” 一聲冷哼從身側(cè)響起凉驻,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎复罐,沒想到半個(gè)月后涝登,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡效诅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年胀滚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乱投。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡咽笼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出戚炫,到底是詐尸還是另有隱情剑刑,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布双肤,位于F島的核電站施掏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏茅糜。R本人自食惡果不足惜七芭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔑赘。 院中可真熱鬧狸驳,春花似錦、人聲如沸米死。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽峦筒。三九已至究西,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間物喷,已是汗流浹背卤材。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留峦失,地道東北人扇丛。 一個(gè)月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像尉辑,于是被迫代替她去往敵國和親帆精。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在,面了一些公司卓练,掛了不少隘蝎,但最終還是拿到小米、百度襟企、阿里嘱么、京東、新浪顽悼、CVTE曼振、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,253評論 11 349
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法蔚龙,內(nèi)部類的語法冰评,繼承相關(guān)的語法,異常的語法府蛇,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理集索,服務(wù)發(fā)現(xiàn)屿愚,斷路器汇跨,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 這部分主要是與Java Web和Web Service相關(guān)的面試題。 96妆距、闡述Servlet和CGI的區(qū)別? 答...
    雜貨鋪老板閱讀 1,405評論 0 10
  • 【帶心旅行Day2】 關(guān)鍵詞#個(gè)人與集體# 關(guān)于救人司機(jī)行為穷遂,先點(diǎn)個(gè)贊,再說高大上的規(guī)矩娱据。 規(guī)矩是死的蚪黑,人是活的,...
    A楊子閱讀 191評論 0 0