java筆記--問題總結

1. 垃圾回收算法

標記-清除算法html

標記-清除算法是最基本的算法,和他的名字同樣,分爲兩個步驟,一個步驟是標記須要回收的對象。在標記完成後統一回收被標記的對象。這個算法兩個問題。一個是效率問題,標記和清除的效率不高。第二個問題是標記-清除以後會有大量不連續的碎片空間,若是咱們須要更大的連續內存就必須GC前端

複製算法java

複製算法,不一樣於標記-清除,複製算法大多數用於新生代,它須要大小相等的兩塊內存,每次只使用一塊內存,當GC的時候會把這塊內存存活的對象複製到另一塊內存上面,解決了時間效率和空間碎片問題。在新生代中會把他分爲三個內存一個Eden 兩個Survivor默認是8比1,開始會使用一個Eden和一個Surivivor裝載內存,清除時會將這兩個保留的對象都保存另外在Survivor中,而且年齡加1(之後提高爲老年代),若是超出了Survivor中的限制會用老年代的內存擔保。mysql

標記-整理算法react

主要特色是,解決了碎片問題。標記整理算法,標記過程和第一算法同樣,可是他處理的時候會讓存活的對象向一邊移動解決了空間碎片問題,用於老年代的處理。linux

分代收集算法nginx

分代收集算法不是新思想,只是把上面的算法結合起來了。c++

2. AtomicInteger實現原理

AtomicInteger使用value來保存值,value是volatile的,保證了可見性。git

對於get方法直接返回value,對於自增一或者添加值使用了CAS自旋鎖,使用了一個死循環,若是cas返回爲true就能夠退出循環。對於CAS 全稱是compare and swap比較和交換,CAS須要三個操做數,一個是變量內存地址,一個是excepted過時值,一個是如今要更新的值,咱們操做的時候僅當V符合舊預期的值的時候才能更新咱們新的。對於它的自增的操做,首先是卸載一個for循環裏面而後得到當前的值,給這個值+1,而後進行cvs要是失敗會再次Get()最新值再次寫.程序員

參考:http://ifeve.com/atomic-operation/

3. synchronizedlock的區別主要有三個區別

用法區別,性能區別,鎖機制的區別。

對於用法區別:synchronized能夠在方法中上使用也能夠在特定代碼塊中使用,括號中表示須要鎖的對象,若是在方法上就是對該對象的鎖,若是是在類的方法上就是類的鎖,使用Lock必須本身用代碼顯示申明什麼時候開啓鎖,什麼時候關閉鎖。synchronized是jvm的底層實現,而Lock是由代碼執行。

對於性能的區別:ReentrantLock 功能上要多於synchronized,多了鎖投票,定時鎖等。若是在小規模的競爭上synchronized效率比較高,若是在大規模的競爭上synchronize就比較低而Lock基本不變、

鎖的機制也不一樣:synchronized得到鎖和釋放鎖都是在塊中,都是自動釋放,不會引發死鎖,而Lock須要本身定位釋放,否則會引發死鎖。在Lock中也使用了tryLock方法用非阻塞的方式獲取鎖。

在lock中用一個鎖變量和隊列維護同步。

gc停頓緣由,如何下降GC停頓

緣由:gc停頓的意思就像是在整個分析期間凍結在某個時間點上,具體的緣由是防止在分析的時候,對象引用關係還在不斷的變化,若是沒有GC停頓頗有可能分析不許確。

如何下降:在Serial的老年代垃圾收集器中,會把全部線程的暫停,停下來收集哪些是死亡對象。在CMS和G1中都採起了初始標記、併發標記、短暫GC停頓從新標記,初始標記會直接記錄能GC ROOTS 關聯的對象,在併發標記的時候有一個線程來標記,這個時候對象的發生的變化都會記錄下來,在從新標記的時候會修正,這樣就會下降GC停頓時間

jvm如何調優,參數怎麼調?如何利用工具分析jvm狀態?

合理的分配內存,分配棧和堆的內存,在堆中咱們還能夠詳細劃分新生代和老年代的內存比例,在新生代中咱們也能夠劃分Eden和Surivior的內存比例(調該比例大小),合理的劃份內存區域大小,能夠幫助咱們jvm調優,咱們採起合適的垃圾回收器,好比在新生代啓用serial垃圾回收器,在老年代採用cms併發標記,能夠下降GC停頓,固然也能夠嘗試去採用G1垃圾回收器

jvm中類加載過程

類加載到類被卸載過程包括7個階段

1.加載

經過類的全限定名把類文件的二進制流加入進來,經過這個字節流(這個二進制流也是咱們代理類的方法),而後經過這個二進制流把靜態存儲結構轉化爲運行時方法區的結構(不包括類變量,類變量在準備階段),在內存中生成一個Class對象,做爲方法區訪問的入口。

2.驗證驗證是驗證Class文件的字節流包含的信息是否符合當前虛擬機的要求規範,防止惡意攻擊、

3.準備在方法區爲類變量分配內存和設置初始值,這個時候的初始值是數據的0值,不是咱們定義的值,若是是常量的話準備階段就會設置爲咱們定義的值

4.解析將符號引用(這裏的符號引用指的是字面量的形式,只須要無歧義地定位到目標)替換爲直接變量

5.初始化類初始化階段是咱們加載過程的最後一步,執行類構造器,合併static語句,有static的順序決定。

6.使用

7.卸載

4. Springbean的加載機制,bean生成具體步驟

Ioc—Inversion of Control,即「控制反轉」,不是什麼技術,而是一種設計思想。Java開發中,Ioc意味着將你設計好的對象交給容器控制,而不是傳統的在你的對象內部直接控制。

spring中Bean的加載機制其實就是IOC容器的初始化,好比咱們這裏定義了一個IOC容器,BeanFactroy的子類ClassXMLPathApplicationContext,在他的構造函數中咱們會把xml路徑寫進去這個步驟就是定位,接下來就是BeanDefiniton的載入,在構造函數當中有一個refresh()的函數,這個就是載入BeanDefinition的接口,這個方法進去以後是一個同步代碼代碼塊,把以前的容器銷燬和關閉建立了一個BeanFatroy,就像對咱們的容器從新啓動同樣,而後咱們對BeanDefiniton載入和解析解析完畢以後會把beanDefinitionbeanName放入BeanFactoryHashMap中維護。在這裏Bean已經被建立完成,而後咱們就像IOC容器索要Bean,若是是第一次索要會觸發依賴注入,會遞歸的調用gebBean實現依賴出入.

5. 講下java鎖的原理

對於synchronized關鍵字,在jvm中在編譯的時候在同步塊的先後造成監視進入和監視退出兩個字節碼,這兩個字節碼都須要一個引用類型的參數來指定要鎖定和解鎖的對象,若是指定了的話就使用指定的對象,若是沒有指定看是類方法仍是對象方法來決定,在執行監視進入的指令的時候,會判斷可否進入,進入成功以後會把鎖計數器加1,若是不成功就會繼續等待和其餘的線程競爭,出鎖的時候會把鎖計數器減1變爲0,也就是釋放了鎖。在這裏要說明一點java的線程時映射到系統原生線程之上,若是要阻塞或者喚醒一個線程都須要操做系統幫忙,這就須要從用戶態轉換到核心態中,所以狀態轉換須要耗費不少的處理器時間。有可能比用戶的代碼執行時間還長。在jdk1.6以後對synchronized優化是很是的號的,好比鎖粗化,鎖自旋,鎖消除。輕量級鎖和偏向鎖。

而對於ReentrantLock是代碼上的實現

6. 線程和進程的區別

進程是一段正在執行的程序,線程也叫做」輕量級進程「,他是程序執行的最小單元,一個進程能夠有多個線程,各個線程之間共享程序的內存空間(好比說堆空間)及一些進程級的資源,進程和進程之間不能共享內存只能共享磁盤文件,線程也有4中狀態:就緒,運行,掛起,死亡。

(新版本)進程是程序執行時的一個實例,從內核的觀點看,進程的目的就是擔當分配系統資源的基本單位。

線程是進程的一個執行流,是cpu調度和分配的基本單位,它是比進程更小的能獨立運行的基本單位。一個進程由幾個線程組成,線程和同屬一個進程的其餘的線程共享進程所擁有的所有資源。

進程-資源分配的最小單位。線程-程序執行的最小單位。

進程由獨立的空間地址,線程沒有單獨的地址空間同一進程內的共享進程的地址空間,只有本身獨立的堆棧和局部變量。對於咱們來講實現一個多線程的任務比實現一個多進程的任務好,

7. 爲何分配線程比分配通常的對象更須要花費更大的代價?

首先他的資源很是「節儉」。咱們知道,在Linux系統下,啓動一個新的進程必須分配給它獨立的地址空間,創建衆多的數據表來維護它的代碼段,堆棧段和數據段,這是一種「昂貴」的多任務工做方式。而運行一個進程中的多個進程,他們彼此之間使用相同的地址空間,共享進程內的大部分數據,啓動一個進程的時間遠大於一個線程的時間。

(1)地址空間:進程內的一個執行單元;進程至少有一個線程;它們共享進程的地址空間;而進程有本身獨立的地址空間;

(2)資源擁有:進程是資源分配和擁有的單位,同一個進程內的線程共享進程的資源

(3)線程是處理器調度的基本單位,但進程不是.

8. Spring AOP是怎麼實現

首先簡單說一下Spring AOP幾個比較重要的名詞:

通知:定義在鏈接點作什麼,爲切面加強提供織入接口,意思就是說加強的內容以及加強的方式

切點:PointCut:決定通知應用於什麼方法上或者類上。(點:方法或者類)

通知器:鏈接切點和通知結合起來,可讓咱們知道那個通知應用於哪一個結點之上,這個結合爲應用使用Ioc容器配置AoP應用

開始咱們使用AOP的時候是用得java編寫的切面通知使用XML配置,後面咱們摒棄了採用@AspectJ註解對其進行標註

而後AOP的實現原理有一個ProxyFactoryBean(代理工廠),這個ProxyFactoryBea是在Spring Ioc環境之中,建立AOP應用的最底層。在ProxyFactoryBean中咱們會配置好通知器Advisor,在ProxyFactory須要爲目標對象生成代理對象。ProxyFactory有一個getObject方法,在咱們IOC容器中若是獲取這個bean會自動調用這個方法,首先第一步初始化通知器鏈,通知器鏈只會初始化一次,使用標誌位判斷,遍歷通知器,把全部通知器加入攔截器鏈,接下來就是代理對象的生成,利用目標對象以及攔截器咱們能夠正確的生成代理對象,這裏生成代理對象有兩種方法一種是jdk一種是cglib,在獲得AopProxy代理對象以後,咱們首先會根據配置來對攔截器是否與當前的調用方法想匹配,若是當前方法匹配就會發揮做用,他會遍歷Proxy代理對象中設置攔截器鏈的全部攔截器,攔截器調用完成以後纔是目標對象的調用,這個時候會有一個註冊機制,在攔截器中運行的攔截器,會註冊,咱們就不須要再判斷。Aop的源代碼中也大量使用了IOC容器,好比從IOC中找到通知器。

9. SpringMVC的主要流程

首先咱們會在web.xml中配置DispathcerServlet,這個就是SpringMVC的入口,DispathcerServlet的父類FrameWorkServlet首先會初始化WebApplicationContext,DispacherServlet初始化了9個組件,初始完畢後咱們開始進入,FramkeworkServlet中作了三件事一個是調用doService模板方法具體處理請求。將當前全部的請求都合併在一個方法裏面和咱們的httpServlet作法有點不一樣,在DispathcerServlet中有一個doService的方法,其中調用了doDispatch這也是最核心的首先根據request找到Handler,根據Handler找到了HderAdapter,用HandlerAdapter處理Handler其中包含一些參數的處理,處理完成後就行方法調用以後獲得結果真後把View渲染給用戶或者把數據發給用戶。

詳細版本:

1.輸入一個網址,好比http請求,首先咱們tomcat服務器,會對請求建立出咱們request和response,而後就交給咱們對應的servlet處理。

10. 建立線程方式

實現runnable接口重寫run方法,繼承Thread,利用線程池來建立。

11. 想讓全部線程都等到一個時刻同時執行有哪些方法

CountDownLatch:CountDownLatch首先咱們在構造函數當中傳入了一個標誌值,而後在須要阻塞的地方調用await(),直到其餘線程把countDown減小完。這個是不可重用的。

CyclicBarrier:和他的名字同樣柵欄,咱們對他的構造函數傳入一個柵欄值,在須要阻塞的地方調用await的時候咱們就對其基礎值加一,直到等於柵欄值。調用CylicBarrier的reset方法能夠對他進行重置。

Semaphore信號量:Semaphore能夠同時控制訪問的線程個數,若是須要這個資源咱們會acquire()以阻塞的方式去請求,若是沒有可用的信號量,就等待,release釋放信號量,這個機制有點相似於鎖。

jdk1.7中提供了一個同步器Phaser,做用和countdownLatch,CyclicBarrier相似,但PHaser的使用方式更爲靈活。使用register註冊方法遞增計數器,使用arriveAndDeregister()方法來遞減計數器,使用arriveAndAwaitAdvane()方法阻塞線程,當計數器歸0喚醒。

12. volatile的做用

參看博客:http://blog.csdn.net/libing13820393394/article/details/48582999

第一:volatile是Java虛擬機提供的最輕量級的同步機制,使變量對全部的線程可見,保證了可見性,可是並不能保證它的原子性。

第二個:禁止指令重排序優化。普通變量僅僅保證在該方法全部依賴賦值結果的地方都能獲取到正確的結果,而不能保證變量賦值操做的順序與程序代碼中的執行同樣。從硬件的方面來講,並非指令任意重拍,他只是把多條指令不安程序規定順序分發給電路處理單元,好比說2*3+5 2*3之間是有依賴,5就能夠排到他們前面。volatile會幫助咱們加入內存屏障防止重排序。volatile讀操做性能消耗與普通變量幾乎沒區別,寫操做會慢一些,由於它須要在本地代碼中插入許多內存屏障指令來保證處理器不發生亂序執行。

注意:對於volatile修飾的變量,jvm只是保證從主內存加載到線程的工做的內存是最新的

13. 談一談java內存模型

(1)java虛擬機規範試圖定義一種JAVA內存模型來屏蔽掉各類硬件和操做系統的內存訪問的差別。

(2)java內存模型的主要目標是定義程序中各個變量的訪問規則,這裏的變量不包含局部變量和方法參數,而是指的是實例字段、靜態字段、和構成數組對象的元素。

(3)java內存模型規定了全部的變量都存儲在主內存中,而線程內的局部變量在本身的工做內存中,而且還有被該線程使用到的變量的主內存 的副本拷貝,線程對變量的操做(讀取、賦值)都在工做內存中進行,不能直接讀寫主內存的變量,不一樣的線程沒法直接訪問對方工做內存的變量,線程鍵的變量值的傳遞須要經過主內存來完成,在內存模型中比較重要的就是工做線程和主內存的交互。

內存之間的交互:

java內存模型定義的操做:

Lock (鎖定)

Unlock(解鎖)

Read(讀取)

Load(載入)

Use(使用)

Assign(賦值)

Store(存儲)

Write(寫入)

變量從主內存到工做內存:按照順序執行read load操做

變量從工做內存到主內存:按照順序執行Store write操做

重排序:

包括:編譯器優化重排序、指令級並行重排序、內存系統重排序

14. 何時使用LinkedList?

首先分寫LinkedList和ArrayList的不一樣,在常常插入和刪除的時候,在實現棧和隊列的時候,不適合隨機查找元素。

15. Object有哪些方法(九大方法),clone是深複製仍是淺複製,finalize通常在何時使用:

wait,notify,notifyall,clone,getclass,toString,equals,hashcode,finalize。

一、Clone()方法

private保護方法,實現對象的淺複製,只有類實現了Clonable接口才能夠調用該方法,不然拋出CloneNotSupportException。clone是淺複製,複製完成後其中的變量引用仍是和之前的同樣,若是要實現深複製須要咱們把全部的變量引用都遞歸複製一次,而後再賦值。(或者額使用序列化,也能夠實現深拷貝)若是咱們要本身實現clone()方法必需要實現克隆接口clonable。

二、Equals()方法

在object中與==是同樣的,子類通常須要重寫該方法

三、hashCode()方法

該方法用於哈希查找,重寫了equals方法通常都要重寫hashcode方法,這個方法在一些具備哈希功能的collection中使用

四、getClass()方法

final方法,得到運行時的類型

五、Wait()方法

使得當前的線程等待該對象的鎖,當前線程必須是該對象的擁有者,也就是具備該對象的鎖。Wait方法會一直等待,直到得到鎖(到了睡眠的時間間隔也會喚醒本身)或者被中斷掉。

調用該方法,當前的線程會進入到睡眠的狀態,直到調用該對象的notify方法、notifyAll方法、調用interrupt中斷該線程,時間間隔到了。

六、Notify()方法

喚醒在該對象上的等待的某個線程

七、notifyAll()方法

喚醒在該對象上的等待到全部的線程

八、toString()方法

把對象轉換成string類型進行輸出

九、finalize()方法

finalize在咱們垃圾回收器回收這個對象的時候工做,能夠作一些後續的工做,即進行一些必要的清理和清除的工做,好比說關閉流。固然咱們也能夠在這個裏面對咱們即將被回收的對象逃出回收。這裏須要注意的是系統只會調用一次finalize()方法。可是通常咱們不推薦使用這個方法,由於這個方法是爲了對開始C和C++程序員的一種妥協,由於C中有析構函數,這個方法運行代價高,不肯定大,咱們仍是會推薦使用try{}finally,他作的方法try{}finally均可以作。

16. 如何管理線程(主要介紹各類線程池的實現)

使用線程池來管理線程

Java中實現多種線程池

咱們使用executors工廠產生咱們的線程池,當線程池達到負載的時候會在咱們線程池管理的Runnable阻塞隊列中等待,不會像線程那樣競爭CPU

第一種 newFixedThreadPool,和它的名字同樣這是一個固定線程池,咱們能夠設置基本大小也就是咱們沒有任何任務執行的時候的大小,最大大小,只有在工做隊列滿了才能達到最大大小。

第二種 newCachedThreadPool這種線程池把大小設置爲Integer.MAX_VALUE,基本大小設置爲0,空閒超時設置1分鐘,這種線程池能夠無限擴展,而且當需求下降時會自動收縮。

第三種 newSingleThreadPool這種線程池把基本大小設置爲1,最大大小都設置爲1,只容許同一時刻一個線程。

固定線程池和單線程池固定默認使用的是阻塞隊列無界的LinkedBlockingQueue,在這個阻塞隊列中能夠無限增加。可是對於咱們的newCachedThreadPool來講他的線程池是無限大的,不須要阻塞等待,咱們這裏使用的是SynchronousQueue來避免排隊,其實這個東西不是一個隊列,是直接在線程之間進行移交,當線程池的大小小於所須要的時候,要麼建立一個要麼拒絕一個。咱們通常在使用的時候能夠擴展,使用使用信號量來控制提交速率。

17. 如何讓線程A等待線程B結束

1.使用join方法能夠等待A線程結束,或者單線程池中 阻塞隊列的方式讓A先得到單線程池的線程,而後B一直阻塞,知道A釋放本身的線程。

18. 如何優化jvm參數

,首先設置堆的大小,通常設置xmx和xms大小相同,若是老年代容易溢出能夠擴充老年代,也要適當的調整永久代大小,選擇本身合適的收集器,調整新生代對象年齡閥值等。

19. 什麼是守護線程

線程會分爲兩種:

普通線程和守護線程。在JVM啓動時建立的全部線程中,除了主線程其餘都是守護線程,好比說垃圾回收器就是守護線程,當普通線程所有退出的時候守護線程也會退出,咱們本身也能夠手動設置手動線程在線程啓動以前,可是咱們應該儘量少使用守護線程,由於咱們不多有操做能夠在不進行清理就能夠安全地拋棄,好比說I/O操做。

20. TCP如何控制擁塞

擁塞控制就是防止過多的數據注入網絡中,這樣能夠使網絡中的路由器或鏈路不致過載。

發送方維持一個叫作擁塞窗口cwnd(congestion window)的狀態變量。

爲了防止cwnd增加過大引發網絡擁塞,還需設置一個慢開始門限ssthresh狀態變量。ssthresh的用法以下:

cwnd時,使用慢開始算法。也就是乘法算法

cwnd>ssthresh時,改用擁塞避免算法。也就是加法算法

cwnd=ssthresh時,慢開始與擁塞避免算法任意。

當出現擁塞的時候就把心的門限值設爲此時窗口大小的通常,窗口大小設置爲1,再從新執行上面的步驟。

當收到連續三個重傳的時候這就須要快重傳和快恢復了,當收到連續三個重傳這個時候發送方就要重傳本身的信息,而後門限減半可是這個時候並非網絡阻塞,窗口只會減半執行擁塞避免算法。

21. ThreadLoacl?

咱們使用ThreadLocal爲每一個使用該類型的變量提供了一個獨立的副本,具體的實現是在每一個線程中保存了一個ThreadLocalMap,這個ThreadLoaclMap會在咱們第一次使用ThreadLoal中的set方法建立出來,set方法就是保存在ThreadLocalMap中,該變量爲key,值爲value,get方法也從這個HashMap中找。

22. OSI網絡模型?

網卡在哪一層(物理層)

交換機在哪一層(鏈路層)

路由器在哪一層(網絡層)

傳輸TCP

會話 SQL

表示 IMG

html在應用層

23. HTTP1.0Http1.1區別?

1.0默認是屢次tcp鏈接屢次請求,而後增長了keep alive功能,可是必須在request Header手動增長Connection:keepalive

1.1是一次tcp鏈接屢次請求,新的persistence功能

24. POSTGET方法的區別?

長的說:

對於GET方式的請求,瀏覽器會把http header和data一併發送出去,服務器響應200(返回數據);

而對於POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。

也就是說,GET只須要汽車跑一趟就把貨送到了,而POST得跑兩趟,第一趟,先去和服務器打個招呼「嗨,我等下要送一批貨來,大家打開門迎接我」,而後再回頭把貨送過去。

由於POST須要兩步,時間上消耗的要多一點,看起來GET比POST更有效。所以Yahoo團隊有推薦用GET替換POST來優化網站性能。但這是一個坑!跳入需謹慎。爲何?

1. GET與POST都有本身的語義,不能隨便混用。

2. 據研究,在網絡環境好的狀況下,發一次包的時間和發兩次包的時間差異基本能夠無視。而在網絡環境差的狀況下,兩次包的TCP在驗證數據包完整性上,有很是大的優勢。

3. 並非全部瀏覽器都會在POST中發送兩次包,Firefox就只發送一次。

1.get是從服務器上獲取數據,post是向服務器傳送數據。

2.get是經過URL來傳遞數據,POST是經過表單傳遞,所以get數據限制在1024k,而POST沒有限制

3.在java服務器端get是經過request.qureySting post經過request.getParameterNames和reque.getParameterValue

4.get是安全的,冪等的 POST即不安全又不冪等(屢次操做和一次操做同樣)

在rest中設計的話,通常get用來查詢數據,POST用來添加數據,PUT用來更新數據,Delete用來刪除數據

25. filter執行順序?

多個filter的執行順序是web.xml中的配置順序

影響SQL執行效率的因素?

1.is null和is not null

2.通配符的like

3.order by

4.not

5.in和exists

GBK和UTF-8的區別

GBK包含所有中文字符; UTF-8則包含全世界全部國家須要用到的字符。

GBK的文字編碼是雙字節來表示的,即不論中、英文字符均使用雙字節來表示,只不過爲區分中文,將其最高位都定成1。

至於UTF-8編碼則是用以解決國際上字符的一種多字節編碼,它對英文使用8位(即一個字節),中文使用24位(三個字節)來編碼。對於英文字符較多的論壇則用UTF-8節省空間。

UTF8是國際編碼,它的通用性比較好,外國人也能夠瀏覽論壇 GBK是國家編碼,通用性比UTF8差,不過UTF8佔用的數據庫比GBK大~

26. stringBufferStringBuilder

1.三者在執行速度方面的比較:StringBuilder >  StringBuffer  >  String

servlet和Filter的實現原理

StringBuffer是線程安全的,St不是線程安全的,內部的實現是使用char數

27. 什麼是rest

一次網站訪問的全過程:

樓主提到TCP/IP分層的時候用的是網絡接口層,那麼樓主的TCP/IP分層概念應該是:應用層、傳輸層、網絡層、網絡接口層(包含了七層模型中的數據鏈路層和物理層)。

我嘗試回答一下樓主的問題,但願你們繼續拍磚,若是訪問www.163.COM這個網站,那麼他的主要過程應該是:

1、主機向DNS服務器發起域名解析請求,以獲得相對應的IP地址

2、應用層應用HTTP協議發送數據

3、數據到達傳輸層封裝成數據段,主機使用1024之後的隨機源端口號,目標端口號爲80

4、數據段到達網絡層封裝成數據包,加入主機源IP地址和目標IP地址

5、數據包到達網絡接口層首先封裝成數據幀,加入源MAC地址和目標MAC地址(注:此目標MAC地址爲本地網關的MAC地址,源和目的MAC地址在數據轉發的過程當中,會由路由器不斷的改變)。封裝後將數據轉換爲物理層的數據流,經過互聯網發送至目標服務器。

28. 何時拋出InvalidMonitorStateException異常?爲何?

調用 wait ()/notify ()/notifyAll ()中的任何一個方法時,若是當前線程沒有得到該對象的鎖,

那麼就會拋出 IllegalMonitorStateException 的異常

也就是說程序在沒有執行對象的任何同步塊或者同步方法時,

仍然嘗試調用 wait ()/notify ()/notifyAll ()時。因爲該異常是 RuntimeExcpetion 的子類,

因此該異常不必定要捕獲(儘管你能夠捕獲只要你願意

做爲 RuntimeException,此類異常不會在 wait (),notify (),notifyAll ()的方法簽名說起。

29. Collections.synchronizedXX 方法的原理

返回了一個同步容器,在這個同步容器中的全部方法都有一個鎖爲當前對象或者指定鎖的同步塊,用這種阻塞同步的方法可讓咱們容器同步

30. 什麼是Future

Future就是對於具體的Runnable或者Callable任務的執行結果進行取消、查詢是否完成、獲取結果。必要時能夠經過get方法獲取執行結果,該方法會阻塞直到任務返回結果。

1.cancel方法用來取消任務

2.isCancelled方法表示任務是否被取消成功,若是在任務正常完成前被取消成功,則返回 true。

3.isDone()表示是否完成

4.get()得到執行結果,這個方法會一直阻塞

5.在時間範圍內獲取執行結果

FutureTask是Future的實現類

31. 說出數據鏈接池的工做機制是什麼?

J2EE服務器啓動時會創建必定數量的池鏈接,並一直維持很多於此數目的池鏈接。

   調用:客戶端程序須要鏈接時,池驅動程序會返回一個未使用的池鏈接並將其表記爲忙。若是當前沒有空閒鏈接,池驅動程序就新建必定數量的鏈接,新建鏈接的數量有配置參數決定。

釋放:當使用的池鏈接調用完成後,池驅動程序將此鏈接表記爲空閒,其餘調用就能夠使用這個鏈接。

數據庫鏈接池在初始化時將建立必定數量的數據庫鏈接放到鏈接池中,這些數據庫鏈接的數量是由最小數據庫鏈接數來設定的。不管這些數據庫鏈接是否被使用,鏈接池都將一直保證至少擁有這麼多的鏈接數量。鏈接池的最大數據庫鏈接數量限定了這個鏈接池能佔有的最大鏈接數,當應用程序向鏈接池請求的鏈接數超過最大鏈接數量時,這些請求將被加入到等待隊列中。

數據庫鏈接池的最小鏈接數和最大鏈接數的設置要考慮到下列幾個因素:

1) 最小鏈接數是鏈接池一直保持的數據庫鏈接,因此若是應用程序對數據庫鏈接的使用量不大,將會有大量的數據庫鏈接資源被浪費;

2) 最大鏈接數是鏈接池能申請的最大鏈接數,若是數據庫鏈接請求超過此數,後面的數據庫鏈接請求將被加入到等待隊列中,這會影響以後的數據庫操做。

3) 若是最小鏈接數與最大鏈接數相差太大,那麼最早的鏈接請求將會獲利,以後超過最小鏈接數量的鏈接請求等價於創建一個新的數據庫鏈接。不過,這些大於最小鏈接數的數據庫鏈接在使用完不會立刻被釋放,它將被放到鏈接池中等待重複使用或是空閒超時後被釋放。

32. 存儲過程和函數的區別

存儲過程是用戶定義的一系列sql語句的集合,涉及特定表或其它對象的任務,用戶能夠調用存儲過程,而函數一般是數據庫已定義的方法,它接收參數並返回某種類型的值而且不涉及特定用戶表。

33. 事務是什麼?

事務是做爲一個邏輯單元執行的一系列操做。

34. 遊標的做用?如何知道遊標已經到了最後?

遊標用於定位結果集的行,經過判斷全局變量@@FETCH_STATUS能夠判斷是否到了最後,一般此變量不等於0表示出錯或到了最後。

35. 系統進程間通訊的方式

管道( pipe ):管道是一種半雙工的通訊方式,數據只能單向流動,並且只能在具備親緣關係的進程間使用。進程的親緣關係一般是指父子進程關係。

命名管道 (named pipe) 命名管道也是半雙工的通訊方式,可是它容許無親緣關係進程間的通訊。

信號量( semophore ) 信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。它常做爲一種鎖機制,防止某進程正在訪問共享資源時,其餘進程也訪問該資源。所以,主要做爲進程間以及同一進程內不一樣線程之間的同步手段。

消息隊列( message queue ) 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。

信號 ( sinal ) 信號是一種比較複雜的通訊方式,用於通知接收進程某個事件已經發生。

共享內存( shared memory ) :共享內存就是映射一段能被其餘進程所訪問的內存,這段共享內存由一個進程建立,但多個進程均可以訪問。共享內存是最快的 IPC 方式,它是針對其餘進程間通訊方式運行效率低而專門設計的。它每每與其餘通訊機制,如信號量,配合使用,來實現進程間的同步和通訊。

套接字( socket ) 套解口也是一種進程間通訊機制,與其餘通訊機制不一樣的是,它可用於不一樣及其間的進程通訊。

36. jvm調優:內存溢出和內存泄露:

溢出解決:

1.在代碼中減小沒必要要的實例構造

2.設置堆和永久代的大小 -xms堆最小 -xmx堆最大

內存泄露:

內存泄露不能經過配置解決代碼的問題。好比資源在使用完畢後沒有釋放,一些對象存在無效引用咱們不能回收。

37. httphttps的區別

http協議是無狀態的明文傳輸,Https而SSL+HTTP協議構建的可進行加密傳輸。https的服務器必須向CA申請一個證實服務器用途的證書,而客戶端經過該證書確認服務器,因此銀行都是https,全部的通信都是在密鑰加密的狀況下,而密鑰則是經過證書交換,因此第三方攔截的數據沒有密鑰也沒有用。

SSL用以保障在Internet上數據傳輸之安全,利用數據加密(Encryption)技術,可確保數據在網絡上之傳輸過程當中不會被截取及竊聽。

38. 虛擬機性能監控情況

jps:顯示系統內全部進程的信息。

jstat:收集虛擬機各類運行狀態信息的命令行工具。 -gc,監視java堆 -class 就是監視類加載,還能夠監視編譯情況。

jinfo:java配置信息工具。

jmap:用於生成堆轉儲快照 有些選項只能在linux下才能看見。

jhat:配合jmap。

jstack:堆棧追蹤。

39. Servlet生命週期

1.加載:在Servlet容器啓動的時候會經過類加載器加載咱們的Servlet的Class文件。

2.建立:在建立過程的時候若是沒有在web.xml文件中使用load-on-startup咱們在第一次訪問咱們的Servlet的時候會初始化實例,若是配置了這個而且大於1會在容器啓動的時候就建立。

3.初始化:init()初始化的方法只會被調用一次。在咱們實例化被建立以後就會執行初始化。

4.處理客戶請求:service()在Servlet的service方法中會根據不一樣的http方法來調用。

5.卸載:destroy()當咱們Servlet須要被卸載的時候就會調用咱們的destory()方法,隨後垃圾回收器會回收。

40. Minor GCFULL GC

當咱們須要向新生代中分配內存時出現不足的狀況:會出現Minor GC,在新生代中 都是朝生夕滅的對象,頻率比較高。Minor GC發生在新生代。

FULL GC指在老年代發生的GC,通常狀況下出現了FULL GC都會伴隨着一次Minor GC。

爲何MinorGC 和FULL GC速度有差距呢?

在Minor GC中使用的copy算法,在FullGC中使用的是標記清除 或者標記整理算法。

copy算法是用空間換時間 mark(標記)和copy(複製)是一個動做。

可是mark-sweap或mark-compact都是分爲兩個階段,先標記再清除是兩步驟。

因此Minro GC速度會快於FullGC。

41. JVM調優問題

對於JVM調優的重點是垃圾回收和內存管理。

垃圾回收咱們能夠使用咱們的cms垃圾回收器。

對於內存管理有:

永久代溢出、棧溢出、堆溢出的狀況

永久代溢出:

針對永久代溢出在JVM默認狀況只有64M的永久代大小,不少東西都須要咱們永久代區內存,尤爲是使用Spring等框架的時候會有cglib的動態字節碼生成class,都會存儲在咱們的永久代。因此咱們須要擴充永久代防止內存溢出。

堆溢出:

對於堆溢出咱們也是比較常見的好比說咱們使用容器的時候沒有釋放內存頗有可能就會致使堆溢出,須要動態擴展。

棧溢出:

對於棧咱們也能夠設置提升。

42. 單例模式

1)惡漢式的單例模式

利用靜態static的方式進行實例化,在類被加載時就會建立實例。

/**

 * 餓漢式實現單例模式

 */

public class Singleton {

  private static Singleton instance = new Singleton();//在類加載時實例單例對象

    private Singleton() {//私有的構造器

    }

    public static Singleton getInstance() {//返回一個實例對象

        return instance;

    }

}

(2)懶漢式實現單例模式

在被第一次引用時纔去建立對象。

/**

 * 懶漢式實現單例模式

 */

public class Singleton {

    private static Singleton instance;//建立私有的靜態變量

    private Singleton() {//私有的構造函數

    }

        // synchronized方法,多線程狀況下保證單例對象惟一

public static synchronized Singleton getInstance() {

//若是實例對象爲空,就從新去實例化

        if (instance == null) {

            instance = new Singleton();

        }

        return instance;

    }

}

分析:這中方法的實現,效率不高,由於該方法定義爲同步的方法。

(3)雙重鎖實現的單例模式double check

/**

 * DCL實現單例模式

 */

public class Singleton {

    private static valotile Singleton instance = null;//這裏要加入valotile關鍵字,避免指令重排序,  可能先賦值可是沒有分配內存

    private Singleton() {

    }

    public static Singleton getInstance() {

        // 兩層判空,第一層是爲了不沒必要要的同步

        // 第二層是爲了在null的狀況下建立實例

        if (instance == null) {

            synchronized (Singleton.class) {

                if (instance == null) {

                    instance = new Singleton();

                }

            }

        }

        return instance;

    }

}

分析:資源的利用率較高,在須要的時候去初始化實例,並且能夠保證線程的安全,該方法沒有去進行同步鎖,效率比較好。

(4)靜態內部類實現單例模式

/**

 * 靜態內部類實現單例模式

 */

public class Singleton {

    private Singleton() {

}

//返回實例的方法

    public static Singleton getInstance() {

        return SingletonHolder.instance;

    }

    /**

     * 靜態內部類

     */

private static class SingletonHolder {

    //靜態私有的實例對象

        private static Singleton instance = new Singleton();

    }

}

分析:第一次加載類時不會去初始化instance,只有第一次調用getInstance()方法時,虛擬機纔會加載內部類,初始化instance

能夠保證線程的安全,單例對象的惟一,延遲了單例的初始化。

(5)枚舉單例

/**

 * 枚舉實現單例模式

 */

public enum SingletonEnum {

    INSTANCE;//直接定義一個實例對象

    public void doSomething() {

        System.out.println("do something");

    }

}

分析:枚舉實例的建立是線程安全的,即便反序列化也不會生成新的實例,在任何的狀況下都是單例的。

43. 設計模式6大原則

1.單一職責。2.里氏替換 3.依賴致使4接口隔離5.迪米特法則6.開閉原則。

44. XMLJSON優缺點

XML的優勢

A.格式統一,符合標準;

B.容易與其餘系統進行遠程交互,數據共享比較方便。

      C.可讀性高

XML的缺點

 A.XML文件龐大,文件格式複雜,傳輸佔帶寬;

 B.服務器端和客戶端都須要花費大量代碼來解析XML,致使服務器端和客戶端代碼變得異常複雜且不易維護;

 C.客戶端不一樣瀏覽器之間解析XML的方式不一致,須要重複編寫不少代碼;

 D.服務器端和客戶端解析XML花費較多的資源和時間。

JSON的優缺點

JSON的優勢:

A.數據格式比較簡單,易於讀寫,格式都是壓縮的,佔用帶寬小;

B.易於解析,客戶端JavaScript能夠簡單的經過eval()進行JSON數據的讀取;

      C.支持多種語言,包括ActionScript, C, C#, ColdFusion, Java, JavaScript, Perl, PHP, Python, Ruby等服務器端語言,便於服務器端的解析;

D.在PHP世界,已經有PHP-JSON和JSON-PHP出現了,偏於PHP序列化後的程序直接調用,PHP服務器端的對象、數組等能直接生成JSON格式,便於客戶端的訪問提取;

E.由於JSON格式能直接爲服務器端代碼使用,大大簡化了服務器端和客戶端的代碼開發量,且完成任務不變,而且易於維護。

JSON的缺點

A.沒有XML格式這麼推廣的深刻人心和喜用普遍,沒有XML那麼通用性;

B.JSON格式目前在Web Service中推廣還屬於初級階段。

       C:可讀性低。

45. 四種讀取XML文件讀取的辦法

1.DOM生成和解析XML文檔

爲XML文檔的已解析版本定義了一組接口。解析器讀入整個文檔,而後構建一個駐留內存的樹結構。

優勢:整個文檔樹在內存中,便於操做;支持刪除,修改,從新排列等。

缺點:  把整個文檔調入內存,存在不少無用的節點,浪費了時間和空間。

2.SAX爲解決DOM

一、邊讀邊解析,應用於大型XML文檔

二、只支持讀

三、訪問效率低

四、順序訪問

3.DOM4J生成和解析XML文檔(解析工具) 性能最好 SUM的JAXM也大量採用DOM4J

HIBERNATE採用DOM4J

雖然DOM4J表明了徹底獨立的開發結果,但最初,它是JDOM的一種智能分支。它合併了許多超出基本XML文檔表示的功能,包括集成的XPath支持、XML Schema支持以及用於大文檔或流化文檔的基於事件的處理。它還提供了構建文檔表示的選項,它經過DOM4J API和標準DOM接口具備並行訪問功能。從2000下半年開始,它就一直處於開發之中。

    爲支持全部這些功能,DOM4J使用接口和抽象基本類方法。DOM4J大量使用了API中的Collections類,可是在許多狀況下,它還提供一些替代方法以容許更好的性能或更直接的編碼方法。直接好處是,雖然DOM4J付出了更復雜的API的代價,可是它提供了比JDOM大得多的靈活性。

    在添加靈活性、XPath集成和對大文檔處理的目標時,DOM4J的目標與JDOM是同樣的:針對Java開發者的易用性和直觀操做。它還致力於成爲比JDOM更完整的解決方案,實如今本質上處理全部Java/XML問題的目標。在完成該目標時,它比JDOM更少強調防止不正確的應用程序行爲。

    DOM4J是一個很是很是優秀的Java XML API,具備性能優異、功能強大和極端易用使用的特色,同時它也是一個開放源代碼的軟件。現在你能夠看到愈來愈多的Java軟件都在使用DOM4J來讀寫XML,特別值得一提的是連Sun的JAXM也在用DOM4J.

4.JDOM

JDOM

優勢:①是基於樹的處理XML的Java API,把樹加載在內存中

        ②沒有向下兼容的限制,所以比DOM簡單

        ③速度快,缺陷少

        ④具備SAX的JAVA規則

缺點:

     ①不能處理大於內存的文檔

     ②JDOM表示XML文檔邏輯模型。不能保證每一個字節真正變換。

     ③針對實例文檔不提供DTD與模式的任何實際模型。

     ④不支持與DOM中相應遍歷包。

最適合於:JDOM具備樹的便利,也有SAX的JAVA規則。在須要平衡時使用

46. 如何防止Sql注入

有兩種辦法

1.第一種消毒,經過正則匹配過濾請求數據中可能注入的SQL。

2.使用預編譯手段preparedStatemengt。

47. DB第一範式,第二範式,第三範式

第一範式:沒一列屬性不可再分,沒有多值屬性

第二範式:在符合第一範式的基礎上,存在主鍵

第三範式:在符合第二範式的基礎上,非關鍵字獨立於其餘的非關鍵字,而且依賴關鍵字。不能存在傳遞依賴。

48. publicprotectedprivate默認權限

private:用於修飾類和方法,只容許該類訪問。

默認:只容許在同一個類和同一個包中進行訪問。

protected:用於修飾類和方法,容許該類和子類訪問以及同一個包中訪問。

public:用於修飾類和方法,容許該包下面和其餘包的訪問,即在全局範圍均可以訪問。

49. 數據庫事務

事務的特性:

原子性:事務是不可再分的;

一致性:事務的實行先後,數據庫的狀態保持一致;

隔離性:事務的併發訪問,事務之間的執行互不干擾;

持久性:事務結束後數據永久保存在數據庫中。

什麼是髒讀?

髒讀就是一個事務讀取了該數據而且對該數據作出了修改,另外一個事務也讀取了該修改後的數據可是前一個事務並無提交,這是髒數據。

讀取到保存在數據庫內存中的數據。

什麼是不可重複讀?

一個事務:在同一個事務中讀取同一數據,獲得的內容不一樣。一個事務讀取另一個事務更新的數據,致使二次的查詢的數據不一致。

什麼是幻讀?

幻讀是當事務不獨立發生的。好比一個事務刪除了全部數據,另外一個事務又插入了一條,那麼第一個事務的用戶會發現表中尚未修改的數據行。一個事務讀取到另一個事務提交的數據,致使查詢的結果不一致的問題。

數據庫的隔離級別:

Read uncommitted:未提交讀:三中都有可能發生

Read committed :已提交讀 避免髒讀

Repeated read:重複讀:避免髒讀 不可重複讀

Serializable:串行化讀   均可以免

50. WebService究竟是什麼

一言以蔽之:WebService是一種跨編程語言和跨操做系統平臺的遠程調用技術。

所謂跨編程語言和跨操做平臺,就是說服務端程序採用java編寫,客戶端程序則能夠採用其餘編程語言編寫,反之亦然!跨操做系統平臺則是指服務端程序和客戶端程序能夠在不一樣的操做系統上運行。

所謂遠程調用,就是一臺計算機a上的一個程序能夠調用到另一臺計算機b上的一個對象的方法,譬如,銀聯提供給商場的pos刷卡系統,商場的POS機轉帳調用的轉帳方法的代碼實際上是跑在銀行服務器上。再好比,amazon,天氣預報系統,淘寶網,校內網,百度等把本身的系統服務以webservice服務的形式暴露出來,讓第三方網站和程序能夠調用這些服務功能,這樣擴展了本身系統的市場佔有率,往大的概念上吹,就是所謂的SOA應用。

其實能夠從多個角度來理解WebService,從表面上看,WebService就是一個應用程序向外界暴露出一個能經過Web進行調用的API,也就是說能用編程的方法經過Web來調用這個應用程序。咱們把調用這個WebService的應用程序叫作客戶端,而把提供這個WebService的應用程序叫作服務端。從深層次看,WebService是創建可互操做的分佈式應用程序的新平臺,是一個平臺,是一套標準。它定義了應用程序如何在Web上實現互操做性,你能夠用任何你喜歡的語言,在任何你喜歡的平臺上寫Web service ,只要咱們能夠經過Web service標準對這些服務進行查詢和訪問。

   WebService平臺須要一套協議來實現分佈式應用程序的建立。任何平臺都有它的數據表示方法和類型系統。要實現互操做性,WebService平臺必須提供一套標準的類型系統,用於溝通不一樣平臺、編程語言和組件模型中的不一樣類型系統。Web service平臺必須提供一種標準來描述Web service,讓客戶能夠獲得足夠的信息來調用這個Web service。最後,咱們還必須有一種方法來對這個Web service進行遠程調用,這種方法實際是一種遠程過程調用協議(RPC)。爲了達到互操做性,這種RPC協議還必須與平臺和編程語言無關。

51. java中鎖的優化

1.減小鎖持有的時間,能夠減小其它線程的等待時間,不能讓一個線程一直控制着某個鎖不釋放,致使競爭加重。

2.減小鎖的粒度,合適的鎖的代碼塊,能夠減小競爭,控制鎖的範圍。

3.鎖分離,將鎖安功能劃分,好比讀寫鎖,讀讀不互斥,讀寫互斥,寫寫互斥,保證了線程的安全,提升了性能。好比阻塞隊列中的take和put

4.鎖粗化,若是對同一個鎖不停的進行請求,同步和釋放,這個消耗是很是的大的,因此適當的時候能夠粗化。

5.鎖消除,編譯器能夠幫助咱們優化好比一些代碼根本不須要鎖。

52. 虛擬機內的鎖優化

1.偏向鎖:偏向當前已經佔有鎖的線程,在無競爭的時候,以前得到鎖的線程再次得到鎖時,會判斷是否偏向鎖指向我,那麼該線程將不用再次得到鎖,直接進入同步塊。

2.輕量級鎖:偏向鎖失敗後,利用cas補救補救失敗就會升級爲重量級鎖。

3.自旋鎖:會作空操做,而且不停地嘗試拿到這個鎖。

53. java中一億個數找前10000個最大的

先利用Hash法去重複,去除大量的以後 而後等量的分紅100 用小頂堆 來得到10000個,再把全部的1萬個都合在一塊兒就OK

54. java中線程的狀態

java中的線程的狀態有5種(新建、就緒、運行、阻塞、結束)

1.新建:建立後還沒有啓動的線程處於這種狀態,新建出一個線程對象。

2.就緒狀態:當針對該對象掉用了start()方法,該線程等待獲取CPU的使用權

3.運行狀態:在就緒狀態下,得到了CPU處於運行狀態。

4.阻塞:

等待阻塞:運行的線程執行wait方法,JVM會把該線程放入等待池

同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被其餘的線程鎖佔用,則jvm會把該線程放入鎖池中。

其餘阻塞:運行的線程在執行sleep()方法或者join()方法時,或者發出IO請求,JVM會把線程置爲阻塞狀態。

5.結束:

也就是咱們的死亡,代表線程結束。

55. Maven的生命週期

maven有三套相互獨立的生命週期

1.clean生命週期

pre-clean,clean,post-clean

2.default生命週期構建項目

1.validate:驗證工程是否正確,全部須要的資源是否可用

2.compile:編譯項目源代碼

3.test:使用合適的單元框架來測試已編譯的源代碼。

4.Package:把已編譯的代碼打包成可發佈的格式,jar。

4)Package:把已編譯的代碼打包成可發佈的格式,好比jar。

5)integration-test:若有須要,將包處理和發佈到一個可以進行集成測試的環境。

6)verify:運行全部檢查,驗證包是否有效且達到質量標準。

7)install:把包安裝到maven本地倉庫,能夠被其餘工程做爲依賴來使用。

8)Deploy:在集成或者發佈環境下執行,將最終版本的包拷貝到遠程的repository,使得其餘的開發者或者工程能夠共享。

3.

site生命週期:創建和發佈項目站點,phase以下

1pre-site:生成項目站點以前須要完成的工做

2)site:生成項目站點文檔

3)post-site:生成項目站點以後須要完成的工做

4)site-deploy:將項目站點發布到服務器

數據庫索引

56. 什麼是索引?

1)索引是對記錄集多個字段進行排序的方法。

2)也是一個數據結構,在一張表中爲一個字段建立索引,將建立另一個數據結構,包含字段的數值以及指向相關記錄的指針,就能夠對該數據結構進行二分法排序,當須要查詢時就能夠下降時間複雜度。

優點:快速存取數據;保證數據記錄的惟一性;實現表和表之間的參照完整性;在使用order by group by子句進行數據的檢索時,利用索引能夠減小排序和分組的時間。

弊端:創建索引表也是會須要額外的空間。

57. 索引的工做原理:

在對錶中記錄進行搜索時並非對錶中的數據進行所有的掃描遍歷,而是查看在索引中定義的有序列,一旦在索引中找到了要查詢的記錄,就會獲得一個指針,它會指向相應的表中數據所保存的位置。

58. 索引的類型:

1)彙集索引:數據頁在物理上的有序的存儲,數據頁的物理順序是按照彙集索引的順序進行排列。在彙集索引中數據頁彙集索引的葉子節點,數據頁之間經過雙向的鏈表形式相鏈接,實際的數據存儲在葉節點中。

2)非彙集索引:葉子節點不存放具體的數據頁信息,只存放索引的鍵值。非彙集索引的葉子節點包含着指向具體數據的指針,數據頁之間沒有鏈接,是相對獨立的。

3)惟一索引:在整個表中僅僅會出現一次(主鍵約束/UNIQUE)

(4)非惟一索引:在提取數據時容許出現重複的值。

(5)單一索引和組合索引

59. 哪些狀況下索引會失效?

1.條件中有or可是先後沒有同時使用索引

2.多列索引,不是使用前面部分

3.like查詢是以%開頭

4.字符類型應該加單引號 防止轉換爲int類型

60. 數據庫查詢優化(Sql)

1應儘可能避免在 where 子句中使用!=或<>操做符,不然將引擎放棄使用索引而進行全表掃描。

2、對查詢進行優化,應儘可能避免全表掃描,首先應考慮在 where order by 涉及的列上創建索引。

3、應儘可能避免在 where 子句中對字段進行 null 值判斷,不然將致使引擎放棄使用索引而進行全表掃描,如:

     select id from t where num is null

能夠在num上設置默認值0,確保表中num列沒有null值,而後這樣查詢:

     select id from t where num=0

4、儘可能避免在 where 子句中使用 or 來鏈接條件,不然將致使引擎放棄使用索引而進行全表掃描,如:

     select id from t where num=10 or num=20

能夠這樣查詢:

     select id from t where num=10

     union all

     select id from t where num=20

 五、下面的查詢也將致使全表掃描:(不能前置百分號)

     select id from t where name like ‘�c%’

若要提升效率,能夠考慮全文檢索。

 六、in not in 也要慎用,不然會致使全表掃描,如:

     select id from t where num in(1,2,3)

對於連續的數值,能用 between 就不要用 in 了:

     select id from t where num between 1 and 3

 7、若是在 where 子句中使用參數,也會致使全表掃描。由於SQL只有在運行時纔會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然 而,若是在編譯時創建訪問計劃,變量的值仍是未知的,於是沒法做爲索引選擇的輸入項。以下面語句將進行全表掃描:

     select id from t where num=@num

能夠改成強制查詢使用索引:

     select id from t with(index(索引名)) where num=@num

 8、應儘可能避免在 where 子句中對字段進行表達式操做,這將致使引擎放棄使用索引而進行全表掃描。如:

     select id from t where num/2=100

應改成:

     select id from t where num=100*2

 九、應儘可能避免在where子句中對字段進行函數操做,這將致使引擎放棄使用索引而進行全表掃描。如:

     select id from t where substring(name,1,3)=’abc’–name以abc開頭的id

     select id from t where datediff(day,createdate,’2005-11-30′)=0–’2005-11-30′生成的id

應改成:

     select id from t where name like ‘abc%’

     select id from t where createdate>=’2005-11-30′ and createdate<’2005-12-1′

 10、不要在 where 子句中的「=」左邊進行函數、算術運算或其餘表達式運算,不然系統將可能沒法正確使用索引。

 11、在使用索引字段做爲條件時,若是該索引是複合索引,那麼必須使用到該索引中的第一個字段做爲條件時才能保證系統使用該索引,不然該索引將不會被使 用,而且應儘量的讓字段順序與索引順序相一致。

 十二、不要寫一些沒有意義的查詢,如須要生成一個空表結構:

     select col1,col2 into #t from t where 1=0

這類代碼不會返回任何結果集,可是會消耗系統資源的,應改爲這樣:

     create table #t(…)

 13、不少時候用 exists 代替 in 是一個好的選擇:

     select num from a where num in(select num from b)

用下面的語句替換:

     select num from a where exists(select 1 from b where num=a.num)

 1四、並非全部索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重複時,SQL查詢可能不會去利用索引,如一表中有字段 sex,male、female幾乎各一半,那麼即便在sex上建了索引也對查詢效率起不了做用。

 15、索引並非越多越好,索引當然能夠提升相應的 select 的效率,但同時也下降了 insert update 的效率,由於 insert update 時有可能會重建索引,因此怎樣建索引須要慎重考慮,視具體狀況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有 必要。

 16.應儘量的避免更新 clustered 索引數據列,由於 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將致使整個表記錄的順序的調整,會耗費至關大的資源。若應用系統須要頻繁更新 clustered 索引數據列,那麼須要考慮是否應將該索引建爲 clustered 索引。

 17、儘可能使用數字型字段,若只含數值信息的字段儘可能不要設計爲字符型,這會下降查詢和鏈接的性能,並會增長存儲開銷。這是由於引擎在處理查詢和鏈接時會 逐個比較字符串中每個字符,而對於數字型而言只須要比較一次就夠了。

 18、儘量的使用 varchar/nvarchar 代替 char/nchar ,由於首先變長字段存儲空間小,能夠節省存儲空間,其次對於查詢來講,在一個相對較小的字段內搜索效率顯然要高些。

 19、任何地方都不要使用 select * from t ,用具體的字段列表代替「*」,不要返回用不到的任何字段。

 20、儘可能使用表變量來代替臨時表。若是表變量包含大量數據,請注意索引很是有限(只有主鍵索引)。

 2一、避免頻繁建立和刪除臨時表,以減小系統表資源的消耗。

 22、臨時表並非不可以使用,適當地使用它們能夠使某些例程更有效,例如,當須要重複引用大型表或經常使用表中的某個數據集時。可是,對於一次性事件,最好使 用導出表。

 23、在新建臨時表時,若是一次性插入數據量很大,那麼能夠使用 select into 代替 create table,避免形成大量 log ,以提升速度;若是數據量不大,爲了緩和系統表的資源,應先create table,而後insert。

 24、若是使用到了臨時表,在存儲過程的最後務必將全部的臨時表顯式刪除,先 truncate table ,而後 drop table ,這樣能夠避免系統表的較長時間鎖定。

 2五、儘可能避免使用遊標,由於遊標的效率較差,若是遊標操做的數據超過1萬行,那麼就應該考慮改寫。

 2六、使用基於遊標的方法或臨時表方法以前,應先尋找基於集的解決方案來解決問題,基於集的方法一般更有效。

 27、與臨時表同樣,遊標並非不可以使用。對小型數據集使用 FAST_FORWARD 遊標一般要優於其餘逐行處理方法,尤爲是在必須引用幾個表才能得到所需的數據時。在結果集中包括「合計」的例程一般要比使用遊標執行的速度快。若是開發時 間容許,基於遊標的方法和基於集的方法均可以嘗試一下,看哪種方法的效果更好。

 28、在全部的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每一個語句後向客戶端發送 DONE_IN_PROC 消息。

 2九、儘可能避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

 30、儘可能避免大事務操做,提升系統併發能力。查詢sql語句中哪些比較慢

1.慢查詢日誌,通常設置查詢超過兩秒就記錄

2.processlist:顯示哪些線程正在運行.

3.explain關鍵字可讓咱們更好的優化

61. 數據庫設計優化:

1.反範式設計,儘可能是單表,能夠高效利用索引

2.能夠使用查詢緩存,Mysql也會自帶查詢緩存

3.儘可能查詢經過搜索引擎查不經過咱們

4.key,value數據庫

62. 鎖的優化策略

1.讀寫分離,鎖分離

2.減小鎖持有時間,能夠減小其餘的鎖的持有時間

3.以正確的順序得到和釋放鎖

4.適當的鎖的範圍擴大或者縮小,控制鎖的粒度

63. Spring Bean中做用域

singleton:單例模式,在整個Spring IoC容器中,使用singleton定義的Bean將只有一個實例。

prototype:原型模式,每次經過容器的getBean方法獲取prototype定義的Bean時,都將產生一個新的Bean實例。

request:對於每次HTTP請求,使用request定義的Bean都將產生一個新實例,即每次HTTP請求將會產生不一樣的Bean實例。只有在Web應用中使用Spring時,該做用域纔有效。

session:對於每次HTTP Session,使用session定義的Bean都將產生一個新實例。一樣只有在Web應用中使用Spring時,該做用域纔有效。

Globalsession:每一個全局的HTTP Session,使用session定義的Bean都將產生一個新實例。典型狀況下,僅在使用portlet context的時候有效。一樣只有在Web應用中使用Spring時,該做用域纔有效。

64. java中啓定時任務

1.利用sleep特性//休眠

2.time和timerTask//定時器

3.ScheduledExecutorService service.scheduleAtFixedRate(runnable, 10, 1, TimeUnit.SECONDS);

 //任務調度服務

65. 操做系統如何進行分頁調度

用戶程序的地址空間被劃分紅若干固定大小的區域,稱爲「頁」,相應地,內存空間分紅若干個物理塊,頁和塊的大小相等。可將用戶程序的任一頁放在內存的任一塊中,實現了離散分配。

66. linux內核的三種主要調度策略:

1SCHED_OTHER 分時調度策略,

2,SCHED_FIFO實時調度策略,先到先服務

3,SCHED_RR實時調度策略,時間片輪轉

67. TCPUDP相關

74.TCP經過什麼方式提供可靠性:

1.超時重發,發出報文段要是沒有收到及時的確認,會重發。

2.數據包的校驗,也就是校驗首部數據和。

3.對失序的數據從新排序

4.進行流量控制,防止緩衝區溢出

5.快重傳和快恢復

6.TCP會將數據截斷爲合理的長度

68. TCPUDP的區別:

1.UDP是無鏈接的,TCP必須三次握手創建鏈接

2.UDP是面向報文,沒有擁塞控制,因此速度快,適合多媒體通訊要求,好比及時聊天,支持一對一,一隊多。多對一,多對多。

3.TCP只能是一對一的可靠性傳輸

TCP的RPC,在協議棧的下層,可以靈活的對字段進行定製,減小網絡傳輸字節數,下降網絡開銷,提升性能,實現更大的吞吐量和併發數。可是實現代價高,底層複雜,難以獲得開源社區的支持,難以實現跨平臺

76.集羣調優

1.load

load是被定義爲特定時間間隔內運行隊列中的平均線程數,uptime查看,通常load不大於3,咱們認爲負載是正常的,若是每一個CPU的線程數大於5,表示負載就很是高了。

2.CPU利用率

查看cpu的消耗的狀況命令:top | grep Cpu

查看磁盤的剩餘空間命令:df -h

查看系統的內存的使用狀況:free -m

69. 心跳檢測方法

1.使用ping命令

對於full gc致使不響應,網絡攻擊這種 ping展現不明確

2.使用curl

訪問咱們的自測地址

3.對不一樣的功能使用curl檢測,在response中加入狀態頭,表示正常

能夠計算qps經過28原則

innodb存儲引擎經過預寫事務日誌的方式保障事務的原子性,也就是在寫入數據以前,先將數據操做寫入日誌,這種成爲預寫日誌

輕量級鎖認爲在程序運行過程當中,絕大部分的鎖,在整個同步週期內都是不存在競爭的,利用cas操做避免互斥開銷。

偏向鎖是jdk1.6中引入的一項優化,甚至能夠省掉CAS操做,偏向鎖偏向第一個得到他鎖的線程,若是在接下來執行過程當中,這個鎖沒有被其餘線程獲取,則持有偏向鎖的線程永遠不須要同步。

70. GC調優

查看GC日誌,根據GC日誌來優化

咱們能夠經過jps找到咱們虛擬機正在運行的進程。參數 經過jps -help瞭解。

Jstat -gc 或者 -gcutil 查看堆使用狀況-class 配合Jps獲得進程

BTrace原理利用hotspot虛擬中的熱替換,把代碼動態的替換到java程序內,可在不須要重啓的時候就能夠排除問題

JConsole

咱們也能夠使用JConsole來分析這是一個圖形化的,比較容易讓咱們操做

使用VisualVM 進行遠程鏈接 使用JMX方式,也有修改tomcat的catalina就好了

71. 內部類去訪問外部變量,爲何須要加final?

題目有點問題,並非全部的外部變量才加final,咱們的內部類訪問咱們的成員變量就不須要加final,可是訪問局部變量就必需要加final,由於方法(main方法)結束咱們棧幀也就銷燬了,可是咱們內部類在堆中並無被銷燬,若是引用了成員變量,這時候被銷燬了確定是不行的,因此咱們就須要成員變量設置爲final,讓其在方法(main方法)結束時不會被銷燬。

72. 泛型

泛型的做用:在咱們沒有泛型的時候,咱們經過對Object的引用來對參數的任意化,任意化有個缺點就是要作顯示的強制類型轉換,強制轉換有一個很差的地方是運行的時候纔會報錯,泛型的好處實在編譯的時候檢查類型安全,因此泛型的特色就是簡單安全,泛型的原理是類型擦除,java的泛型是僞泛型,在編譯期間,全部的泛型信息都會被擦除掉。在生成的java字節碼中是不包含泛型中的類型信息的。使用泛型的時候加上的類型參數,會在編譯器編譯的時候去掉。好比List

73. nginxapache的對比

1.nginx相對於apache來講

(1輕量級佔用的內存少;

(2)抗併發,nginx是異步非阻塞,apache是阻塞的,在高併發的狀況下,nginx的性能優;

(3)高度模塊化的設計,編寫模塊相對簡單;

(4)社區活躍,各類高性能模塊有。

適合場景:apache適合於動態的請求,而負載均衡和靜態請求適合nginx,nginx採用的是epoll,而且有本身的一套sendfile系統,減小在內存中的賦值次數。

2.apache 相對於nginx 的優勢:

(1)rewrite ,比nginx 的rewrite 強大

(2)模塊超多,基本想到的均可以找到;

(3)少bug ,nginx 的bug 相對較多

(4)超穩定。

74. 線程、進程共享和獨立

共享的部分:

1.進程代碼段

2.進程的公有數據(利用這些共享的數據,線程很容易的實現相互之間的通信)

3.進程打開的文件描述符、

4.信號的處理器、

5.進程的當前目錄

6.進程用戶ID與進程組ID

線程獨有的內容包括:

1.線程ID

2.寄存器組的值

3.線程的堆棧

4.錯誤返回碼

5.線程的信號屏蔽碼

最大的優點就是線程極高的執行效率。由於子程序切換不是線程切換,而是由程序自身控制,所以,沒有線程切換的開銷,和多線程比,線程數量越多,線程的性能優點就越明顯。

第二大優點就是不須要多線程的鎖機制,由於只有一個線程,也不存在同時寫變量衝突,在線程中控制共享資源不加鎖,只須要判斷狀態就行了,因此執行效率比多線程高不少。

75. 簡單的說一下nginx的優勢

1.做爲高性能的web服務器:相比Apache,Nginx使用更少的資源,支持更多的併發鏈接,體現更高的效率,這點讓Nginx受到虛擬主機提供商的歡迎。一個Nginx實例可以輕鬆支持高達5萬併發。

2.做爲負載均衡服務器:Nginx即能夠在內部直接支持PHP,也能夠支持做爲HTTP代理服務器對外進行服務,獨有的send files系統,減小文件複製次數

3.做爲郵件代理服務器:也比Apache好不少。

4.Nginx安裝簡單,配置文件很是簡潔。啓動容易,7*24小時幾乎不間斷,能夠進行熱更新。

76. BIO

在BIO中讀和寫都是同步阻塞的,阻塞的時間取決於對方I/O線程的處理速度和網絡的傳輸速度。本質上來說,咱們是沒法保證生產環境的網絡情況和對端的應用程序能夠足夠快,應用程序是不該該依賴對方的處理速度,它的可靠性就很是差。BIO就算用線程池實現,要是全部可用線程都被阻塞到故障點中,後續的全部I/O消息都將在隊列中排隊。

77. NIO

1)提供了高速,面向塊的I/O

2)在NIO中全部數據都是用緩衝區來處理的,也就是使用咱們的jvm中的direct memory(直接內存)。緩衝區是一個數組,可是緩衝區不只僅是一個數組,緩衝區提供了對數據的結構化訪問以及維護讀寫位置等信息。

3)在NIO中channel(通道)也是特別重要的他是咱們數據讀寫的通道,通常來講流好比inputStream和outputStream都是單向的,而通道是雙向的,是全雙工的

4)多路複用器Selector也是比較重要的,掌握它對於咱們的NIO編程來講是比較重要的。多路複用器提供選擇已經就緒的任務的能力。Selector會不斷輪訓註冊在其上的Channel,若是某個Channel上面發生讀或者寫事件,這個Channel就處於就緒狀態,會被Selector輪詢出來,經過SelectionKey能夠獲取就緒Channel的集合,進行後續的I/o操做。咱們只須要一個線程就能夠管理咱們多個客戶端。

78. 垃圾收集器

1.Serial收集器

    Serial收集器是JAVA虛擬機中最基本、歷史最悠久的收集器,在JDK 1.3.1以前是JAVA虛擬機新生代收集的惟一選擇。Serial收集器是一個單線程的收集器,但它的「單線程」的意義並不只僅是說明它只會使用一個 CPU或一條收集線程去完成垃圾收集工做,更重要的是在它進行垃圾收集時,必須暫停其餘全部的工做線程,直到它收集結束。

     Serial收集器到JDK1.7爲止,它依然是JAVA虛擬機運行在Client模式下的默認新生代收集器。它也有着優於其餘收集器的地方:簡單而高 效(與其餘收集器的單線程比),對於限定單個CPU的環境來講,Serial收集器因爲沒有線程交互的開銷,專心作垃圾收集天然能夠得到最高的單線程收集 效率。在用戶的桌面應用場景中,分配給虛擬機管理的內存通常來講不會很大,收集幾十兆甚至一兩百兆的新生代(僅僅是新生代使用的內存,桌面應用基本上不會 再大了),停頓時間徹底能夠控制在幾十毫秒最多一百多毫秒之內,只要不是頻繁發生,這點停頓是能夠接受的。因此,Serial收集器對於運行在 Client模式下的虛擬機來講是一個很好的選擇。

2. Parallel(並行)收集器

這是 JVM 的缺省收集器。就像它的名字,其最大的優勢是使用多個線程來經過掃描並壓縮堆。串行收集器在GC時會中止其餘全部工做線程(stop-the- world),CPU利用率是最高的,因此適用於要求高吞吐量(throughput)的應用,但停頓時間(pause time)會比較長,因此對web應用來講就不適合,由於這意味着用戶等待時間會加長。而並行收集器能夠理解是多線程串行收集,在串行收集基礎上採用多線 程方式進行GC,很好的彌補了串行收集的不足,能夠大幅縮短停頓時間(以下圖表示的停頓時長高度,併發比並行要短),所以對於空間不大的區域(如 young generation),採用並行收集器停頓時間很短,回收效率高,適合高頻率執行。

3.CMS收集器

    CMS(Concurrent Mark Sweep)收集器是基於「標記-清除」算法實現的,它使用多線程的算法去掃描堆(標記)並對發現的未使用的對象進行回收(清除)。整個過程分爲6個步驟,包括:

初始標記(CMS initial mark)

併發標記(CMS concurrent mark)

併發預清理(CMS-concurrent-preclean)

從新標記(CMS remark)

併發清除(CMS concurrent sweep)

併發重置(CMS-concurrent-reset)

其中初始標記、從新標記這兩個步驟仍然須要「Stop The World」。初始標記僅僅只是標記一下GC Roots能直接關聯到的對象,速度很快,併發標記階段就是進行GC Roots Tracing的過程,而從新標記階段則是爲了修正併發標記期間,因用戶程序繼續運做而致使標記產生變更的那一部分對象的標記記錄,這個階段的停頓時間一 般會比初始標記階段稍長一些,但遠比並發標記的時間短。其餘動做都是併發的。

須要注意的是,CMS收集器沒法處理浮動垃圾(Floating Garbage),可能出現「Concurrent Mode Failure」失敗而致使另外一次Full GC的產生。因爲CMS併發清理階段用戶線程還在運行着,伴隨程序的運行天然還會有新的垃圾不斷產生,這一部分垃圾出如今標記過程以後,CMS沒法在本次 收集中處理掉它們,只好留待下一次GC時再將其清理掉。這一部分垃圾就稱爲「浮動垃圾」。也是因爲在垃圾收集階段用戶線程還須要運行,即還須要預留足夠的 內存空間給用戶線程使用,所以CMS收集器不能像其餘收集器那樣等到老年代幾乎徹底被填滿了再進行收集,須要預留一部分空間提供併發收集時的程序運做使 用。在默認設置下,CMS收集器在老年代使用了68%的空間後就會被激活,這是一個偏保守的設置,若是在應用中老年代增加不是太快,能夠適當調高參數 -XX:CMSInitiatingOccupancyFraction的值來提升觸發百分比,以便下降內存回收次數以獲取更好的性能。要是CMS運行期 間預留的內存沒法知足程序須要,就會出現一次「Concurrent Mode Failure」失敗,這時候虛擬機將啓動後備預案:臨時啓用Serial Old收集器來從新進行老年代的垃圾收集,這樣停頓時間就很長了。因此說參數-XX:CMSInitiatingOccupancyFraction設置 得過高將會很容易致使大量「Concurrent Mode Failure」失敗,性能反而下降。

try catch有return 在字節碼中 能夠看到會出現Goto跳轉行數,跳轉到finally中的return

79. Tomcat總結構

最外層的Server提供接口訪問內部的Service服務。

Service服務的做用就是把Connector 在Connetor中監聽端口和Container鏈接起來,方便咱們的操縱控制。

在tomcat中生命週期是統一的由Lifecycle來管理的

在lifecycle中有兩個方法比較重要start和stop,調用server的start會去調用本身下面全部service的start方法

Connector最重要的功能就是接受鏈接請求而後分配線程處理

在Container 4個級別Engine,Host,Context,warpper,這四個組件不是平行的,而是父子關係,Engine 包含 Host,Host 包含 Context,Context 包含 Wrapper。一般一個 Servlet class 對應一個 Wrapper,若是有多個 Servlet 就能夠定義多個 Wrapper,若是有多個 Wrapper 就要定義一個更高的 Container 了,如 Context。在Host中有個value比較重要,相似於一個管道,和攔截器鏈差很少,咱們在中間能夠進行一些處理。

Engine中只能添加子容器Host,不能添加父容器.Engine下能夠配置多個虛擬主機Virtual Host,每一個虛擬主機都有一個域名

當Engine得到一個請求時,它把該請求匹配到某個Host上,而後把該請求交給該Host來處理Engine有一個默認虛擬主機,當請求沒法匹配到任何一個Host上的時候,將交給該默認Host來處理

一個Host就相似於一個虛擬主機,用來管理應用。表明一個Virtual Host,虛擬主機,每一個虛擬主機和某個網絡域名Domain Name相匹配

每一個虛擬主機下均可以部署(deploy)一個或者多個Web App,每一個Web App對應於一個Context,有一個Context path

當Host得到一個請求時,將把該請求匹配到某個Context上,而後把該請求交給該Context來處理

匹配的方法是「最長匹配」,因此一個path==""的Context將成爲該Host的默認Context

全部沒法和其它Context的路徑名匹配的請求都將最終和該默認Context匹配。

Context 表明 Servlet 的 Context,它具有了 Servlet 運行的基本環境,理論上只要有 Context 就能運行 Servlet 了。簡單的 Tomcat 能夠沒有 Engine 和 Host。

Context 最重要的功能就是管理它裏面的 Servlet 實例,Servlet 實例在 Context 中是以 Wrapper 出現的,還有一點就是 Context 如何才能找到正確的 Servlet 來執行它呢?

一個Context對應於一個Web Application,一個Web Application由一個或者多個Servlet組成

Context在建立的時候將根據配置文件" role="presentation" style='font-size:14px;font-style:normal;font-weight:normal;color:rgb(0, 0, 0);'>CATALINAHOME/conf/web.xml和WEBAPP_HOME/WEB-INF/web.xml載入Servlet類

當Context得到請求時,將在本身的映射表(mapping table)中尋找相匹配的Servlet類

若是找到,則執行該類,得到請求的迴應,並返回.

80. 線程池參數

JDK1.5中引入了強大的concurrent包,其中最經常使用的莫過了線程池的實現。ThreadPoolExecutor(線程池執行器),它給咱們帶來了極大的方便,但同時,對於該線程池不恰當的設置也可能使其效率並不能達到預期的效果,甚至僅至關於或低於單線程的效率。

ThreadPoolExecutor類可設置的參數主要有:

(1)corePoolSize  基本大小

核心線程數,核心線程會一直存活,即便沒有任務須要處理。當線程數小於核心線程數時,即便現有的線程空閒,線程池也會優先建立新線程來處理任務,而不是直接交給現有的線程處理。

核心線程在allowCoreThreadTimeout被設置爲true時會超時退出,默認狀況下不會退出。

(2)maxPoolSize  最大大小

當線程數大於或等於核心線程corePoolSize,且任務隊列已滿時,線程池會建立新的線程,直到線程數量達到maxPoolSize。若是線程數已等於maxPoolSize,且任務隊列已滿,則已超出線程池的處理能力,線程池會拒絕處理任務而拋出異常。

 keepAliveTime  大於coolPoolSize 會退出

當線程空閒時間達到keepAliveTime,該線程會退出,直到線程數量等於corePoolSize。若是allowCoreThreadTimeout設置爲true,則全部線程均會退出直到線程數量爲0。

 allowCoreThreadTimeout  是否退出核心線程

是否容許核心線程空閒退出,默認值爲false。

 queueCapacity

任務隊列容量。從maxPoolSize的描述上能夠看出,任務隊列的容量會影響到線程的變化,所以任務隊列的長度也須要恰當的設置。

81. 線程池按如下行爲執行任務

當線程數小於核心線程數時,建立線程。

當線程數大於等於核心線程數,且任務隊列未滿時,將任務放入任務隊列。

當線程數大於等於核心線程數,且任務隊列已滿

若線程數小於最大線程數,建立線程

若線程數等於最大線程數,拋出異常,拒絕任務

系統負載

參數的設置跟系統的負載有直接的關係,下面爲系統負載的相關參數:

 tasks,每秒須要處理的最大任務數量

 tasktime,處理每一個任務所須要的時間

 responsetime,系統容許任務最大的響應時間,好比每一個任務的響應時間不得超過2秒。

參數設置

corePoolSize:

每一個任務須要tasktime秒處理,則每一個線程每鈔可處理 1/tasktime個任務。系統每秒有tasks個任務須要處理,則須要的線程數爲:tasks/(1/tasktime),即 tasks*tasktime個線程數。假設系統每秒任務數爲100~1000,每一個任務耗時0.1秒,則須要100*0.1至1000*0.1,即 10~100個線程。那麼corePoolSize應該設置爲大於10,具體數字最好根據8020原則,即80%狀況下系統每秒任務數,若系統80%的情 況下第秒任務數小於200,最多時爲1000,則corePoolSize可設置爲20。

queueCapacity:

任務隊列的長度要根據核心線程數,以及系統對任務響應時間的要求有關。隊列長度能夠設置爲(corePoolSize/tasktime)*responsetime (20/0.1)*2=400,即隊列長度可設置爲400。

隊列長度設置過大,會致使任務響應時間過長,切忌如下寫法:

LinkedBlockingQueue queue = new LinkedBlockingQueue();

這其實是將隊列長度設置爲Integer.MAX_VALUE,將會致使線程數量永遠爲corePoolSize,不再會增長,當任務數量陡增時,任務響應時間也將隨之陡增。

maxPoolSize:

當系統負載達到最大值時,核心線程數已沒法按時處理完全部任務,這時就須要增長線程。每秒200個任務須要20個線程,那麼當每秒達到1000個任務時,則須要(1000-queueCapacity)* (20/200),即60個線程,可將maxPoolSize設置爲60。

keepAliveTime:

線程數量只增長不減小也不行。當負載下降時,可減小線程數量,若是一個線程空閒時間達到keepAliveTiime,該線程就退出。默認狀況下線程池最少會保持corePoolSize個線程。

allowCoreThreadTimeout:

默認狀況下核心線程不會退出,可經過將該參數設置爲true,讓核心線程也退出。

以上關於線程數量的計算並無考慮CPU的狀況。若結合CPU的狀況,好比,當線程數量達到50時,CPU達到100%,則將 maxPoolSize設置爲60也不合適,此時若系統負載長時間維持在每秒1000個任務,則超出線程池處理能力,應設法下降每一個任務的處理時間 (tasktime)。

使用ThreadLocal解決SimpleDateFormat,

privatestatic ThreadLocal threadLocal = new ThreadLocal() {        @Override        protected DateFormat initialValue() {            returnnew SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        }    };

或者推薦Joda-Time處理時間比較推薦

在java線程中有6個狀態也就是Thread中的枚舉類

NEW,RUNNABLE,WAITING,TIME_WAITING,BLOCKED,TERMINATED

應該在try{} catch{}中從新設置中斷狀態,由於發出中斷異常被退出了。

82. java內存模型

jvm規範定了jvm內存模型來屏蔽掉各類操做系統,虛擬機實現廠商和硬件的內存訪問差別,確保java程序在全部操做系統和平臺上可以實現一次編寫,處處運行的效果。

83. 爲何IP協議也可以進行數據的不可靠傳輸,還須要Udp

1.咱們須要端口號來實現應用程序間的區分

2.UDP校驗和能夠實現傳輸層的校驗,雖然UDP協議不具有糾錯能力,可是能夠對出錯的數據包進行丟棄,而IP的校驗只是在校驗IP報頭,而不是整個數據包,整個數據包的校驗是在傳輸層完成的,若是出錯了,就會把出錯的數據包丟棄。這也就是爲何須要有傳輸層

84. 進程通訊中管道和共享內存誰的速度快?

1.管道通訊方式的中間介質是文件,一般稱這種文件爲管道文件。兩個進程利用管道進行通訊,一個進程爲寫進程,另外一個進程爲讀進程。寫進程經過往管道文件中寫入信息,讀進程經過讀端從管道文件中讀取信息,這樣的方式進行通訊。

2.共享內存是最快的可用IPC形式,他經過把共享的內存空間映射到進程的地址空間,進程間的數據傳遞不在經過執行任何進入內核的系統調用,節約了時間。java內存模型就採用的是共享內存的方式。各個進程經過公共的內存區域進行通訊。

85. java線程池shutdownshutdownNow的區別?

Shutdown()方法

當線程池調用該方法時,線程池的狀態則馬上變成SHUTDOWN狀態。此時,則不能再往線程池中添加任何任務,不然將會拋出RejectedExecutionException(拒絕執行異常)異常。可是,此時線程池不會馬上退出,直到添加到線程池中的任務都已經處理完成,纔會退出。

shutdownNow()方法

根據JDK文檔描述,大體意思是:執行該方法,線程池的狀態馬上變成STOP狀態並試圖中止全部正在執行的線程,再也不處理還在池隊列中等待的任務,固然,它會返回那些未執行的任務。

它試圖終止線程的方法是經過調用Thread.interrupt()方法來實現的,可是你們知道,這種方法的做用有限,若是線程中沒有sleep 、wait、Condition、定時鎖等應用, interrupt()方法是沒法中斷當前的線程的。因此,ShutdownNow()並不表明線程池就必定當即就能退出,它可能必需要等待全部正在執行的任務都執行完成了才能退出。

86. Integer的裝箱和拆箱的基本原理

Integer包裝類是Java最基本的語法糖優化,若是咱們寫一段程序,經過反編譯就會看到,經過的是Integer.valueOf()或者Interger.intValue()來進行轉換的。

Integer和int比較會自動拆箱,

當Integer和integer比較的時候是不會自動拆箱的,除非遇到了算術符,纔會調用intValue()方法去拆箱。而且在Integer中的equals是不會處理數據類型轉換關係的,使用時是須要慎用,在equals方法中判斷爲Integer類的纔會執行真正的判斷流程也就是拆箱去判斷,因此不會處理數據類型轉換好比Long。若是是基本類型比較,編譯器會隱形的把int轉換爲long,就能夠得出正確的結論。

87. 爲何不推薦使用resumesuspend

由於在使用suspend()去掛起線程的時候,suspend在致使線程暫停的同時,不會去釋聽任何鎖的資源。必需要等待resume()操做,被掛起的線程才能繼續。若是咱們resume()操做意外地在suspend()前就執行了,那麼被掛起的線程可能很難有機會被繼續執行。而且,更嚴重的是:所佔用的鎖不會被釋放,所以可能會致使整個系統工做不正常

yield是謙讓,調用後會使當前線程讓出CPU,可是注意的地方讓出CPU並不表示當前線程不執行了。當前線程在讓出CPU後,還會進行CPU資源的爭奪,有可能剛剛一讓立刻又進。

88. 數據庫事務的隔離級別

1.未提交讀 都不能解決

2.已提交讀 能解決髒讀

3.可重複讀 能解決髒讀,不可重複讀

4.序列化讀 能解決髒讀,不可重複讀,幻讀

89. Docker和虛擬機的比較

1.傳統的虛擬機在宿主機操做系統上面會利用虛擬機管理程序去模擬完整的一個虛擬機操做系統,docker只是在操做系統上的虛擬化,直接複用本地主機的操做系統,很是輕量級。

docker啓動速度通常在秒級,虛擬機啓動速度通常在分鐘級。

2.對於資源的使用通常是mb,一臺機器能夠有上千個docker容器,可是虛擬機佔用資源爲GB,只能支持幾個。

3.性能:接近原生,因爲又虛擬化了一層因此效率低。

4.docker採用相似git的命令學習升本低,指令簡單。

5.虛擬機隔離性是徹底隔離,容器是安全隔離

90. lucence組件

每個詞都會有一個倒排表,多個能夠合併

爲了標識webSocket:會在請求頭中寫一個upgrade:webSocket

HTTP比較

一樣做爲應用層的協議,WebSocket在現代的軟件開發中被愈來愈多的實踐,和HTTP有不少類似的地方,這裏將它們簡單的作一個純我的、非權威的比較:

相同點

都是基於TCP的應用層協議。

都使用Request/Response模型進行鏈接的創建。

在鏈接的創建過程當中對錯誤的處理方式相同,在這個階段WS可能返回和HTTP相同的返回碼。

均可以在網絡中傳輸數據。

不一樣點

 WS使用HTTP來創建鏈接,可是定義了一系列新的header域,這些域在HTTP中並不會使用。

 WS的鏈接不能經過中間人來轉發,它必須是一個直接鏈接。

 WS鏈接創建以後,通訊雙方均可以在任什麼時候刻向另外一方發送數據。f

 WS鏈接創建以後,數據的傳輸使用幀來傳遞,再也不須要Request消息。

 WS的數據幀有序。

91. 微服務架構

首先看一下微服務架構的定義:微服務(MSA)是一種架構風格,旨在經過將功能分解到各個離散的服務中以實現對解決方案的解耦。它有以下幾個特徵:

小,且只幹一件事情。

獨立部署和生命週期管理。

異構性

輕量級通訊,RPC或者Restful。

92. BIO通訊模型圖:

BIO以是一客戶端一線程,一個Acceptor線程來接受請求,以後爲每個客戶端都建立一個新的線程進行鏈路處理,最大的問題缺少彈性伸縮能力,客戶端併發訪問量增長後,線程數急劇膨脹。能夠用線程池緩解可是仍是不行。

NIO非阻塞IO解決了這個問題,一個線程就能夠管理多個Socket.

在NIO中有三個須要咱們瞭解Buffer,Channel,Selector

Buffer:NIO是面向緩衝區,IO是面向流的。緩衝區實質上一個數組

,緩衝區不只僅是一個數組,緩衝區提供了對數據結構化訪問以及維護讀寫位置等信息。

通道Channel:

Channel是一個通道,網絡數據經過Channel讀取和寫入。通道與流的不一樣之處在於通道是雙向的,流是一個方向上移動,通道能夠用於讀寫操做,特別是在UNIX網絡編程模型底層操做系統的通道都是全雙工的,同時支持讀寫操做。

Selector:多路複用器NIo編程的基礎,多路複用器提供選擇就緒任務的 能力。簡單來講Selector會不斷註冊在其上的Channel,若是某個Channel上面發生讀或者寫時間,這個Channel就處於就緒狀態,會被Selector輪詢出來,經過SelectionKey,一個多路複用器能夠同時輪詢多個Channel,JDK使用了epoll代理傳統select實現,因此沒有最大鏈接句柄fd的限制,意味着一個線程負責Selector的輪詢,就能夠接入成千上萬的客戶端

select/poll epoll select poll順序掃描fd,就緒就返回fd。epoll則是 採用事件驅動,用回調的方式返回fd。

93. 面向對象設計七大原則

1. 單一職責原則(Single Responsibility Principle

每個類應該專一於作一件事情。

2. 里氏替換原則(Liskov Substitution Principle

超類存在的地方,子類是能夠替換的。

3. 依賴倒置原則(Dependence Inversion Principle

實現儘可能依賴抽象,不依賴具體實現。

4. 接口隔離原則(Interface Segregation Principle

應當爲客戶端提供儘量小的單獨的接口,而不是提供大的總的接口。

5. 迪米特法則(Law Of Demeter

又叫最少知識原則,一個軟件實體應當儘量少的與其餘實體發生相互做用。

6. 開閉原則(Open Close Principle

面向擴展開放,面向修改關閉。

7. 組合/聚合複用原則(Composite/Aggregate Reuse Principle CARP

儘可能使用合成/聚合達到複用,儘可能少用繼承。原則: 一個類中有另外一個類的對象。

94. 攔截器和過濾器的區別

強類型:不容許隱形轉換

弱類型:容許隱形轉換

靜態類型:編譯的時候就知道每個變量的類型,由於類型錯誤而不能作的事情是語法錯誤.

動態類型:編譯得時候不知道每個變量的類型,由於類型錯誤而不能作的事情是運行時錯誤

編譯語言和解釋語言:解釋性編程語言,每一個語句都是執行的時候才翻譯並且是一句一句的翻譯就很低。

編譯的語言就只須要一次就能夠了

95. 繼承Thread 接口Runnabel的區別

主要是繼承和實現接口的兩個區別,若是隻想重寫run方法就能夠使用,若是不重寫其餘方法 就使用runnable,若是使用實現接口的實現,讓本身方便管理線程以及讓線程複用,能夠使用線程池去建立。

96. hash算法(特色、哈希函數構造、解決衝突的策略)

哈希表的概念:

哈希表就是一種以鍵-值(key-indexed) 存儲數據的結構,咱們只要輸入待查找的值即key,便可查找到其對應的值。

哈希表的實現思路:

若是全部的鍵都是整數,那麼就能夠使用一個簡單的無序數組來實現:將鍵做爲索引,值即爲其對應的值,這樣就能夠快速訪問任意鍵的值。這是對於簡單的鍵的狀況,咱們將其擴展到能夠處理更加複雜的類型的鍵。對於衝突的狀況,則須要處理地址的衝突問題。因此,一方面要構造出良好的哈希函數,對鍵值集合進行哈希,另一方面須要設計出良好的解決衝突的算法,處理哈希碰撞的衝突。

哈希表的查找步驟:

(1)使用哈希函數將被查找的鍵轉換爲數組的索引。在理想的狀況下,不一樣的鍵會被轉換爲不一樣的索引值,可是在有些狀況下咱們須要處理多個鍵被哈希到同一個索引值的狀況。因此哈希查找的第二個步驟就是處理衝突

(2)處理哈希碰撞衝突。有不少處理哈希碰撞衝突的方法,本文後面會介紹拉鍊法線性探測法

哈希表的思想:

是一個在時間和空間上作出權衡的經典例子。若是沒有內存限制,那麼能夠直接將鍵做爲數組的索引。那麼全部的查找時間複雜度爲O(1);若是沒有時間限制,那麼咱們能夠使用無序數組並進行順序查找,這樣只須要不多的內存。哈希表使用了適度的時間和空間來在這兩個極端之間找到了平衡。只須要調整哈希函數算法便可在時間和空間上作出取捨。

哈希表的工做步驟:

 1)   哈希(Hash)函數是一個映象,即將關鍵字的集合映射到某個地址集合上,它的設置很靈活,只要這個地址集合的大小不超出容許範圍便可;

 2)  因爲哈希函數是一個壓縮映象,所以,在通常狀況下,很容易產生「衝突」現象,即: key1!=key2,而  f  (key1) = f(key2)。鍵不一樣,可是對應的取值相同。

3).  只能儘可能減小衝突而不能徹底避免衝突,這是由於一般關鍵字集合比較大,其元素包括全部可能的關鍵字,而地址集合的元素僅爲哈希表中的地址值。

哈希函數的構造方法:

一、直接地址法

以數據元素的關鍵字k自己或者他的線性的函數做爲它 的哈希地址,也就是H(k)=k,或者H(k)=a*k+b;

適用的場景:地址集合的大小==關鍵字的集合。

二、數字分析法

取數據元素關鍵字中某些取值較均勻的數字位做爲哈希地址的方法

適用的場景:能預先估計出全體關鍵字的每一位上各類數字出現的頻度。

三、摺疊法

將關鍵字分割成位數相同的幾部分(最後一部分的位數能夠不一樣),而後取這幾部分的疊加和(捨去進位),這方法稱爲摺疊法

適用場景:關鍵字的數字位數特別多。

四、平方取中法

先取關鍵字的平方,而後根據可以使用空間的大小,選取平方數是中間幾位爲哈希地址。

適用場景:經過取平方擴大差異,平方值的中間幾位和這個數的每一位都相關,則對不一樣的關鍵字獲得的哈希函數值不易產生衝突,由此產生的哈希地址也較爲均勻。

五、減去法

六、基數轉換法

七、除留餘數法

八、隨機數法

九、隨機乘數法

十、旋轉法

構造哈希哈希函數的原則:

一、計算哈希函數的時間

二、關鍵子的長度

三、哈希表的長度

四、關鍵字的分佈的狀況

五、記錄查找頻率

哈希函數的衝突解決的方法:

一、開放地址法

這種方法也稱再散列法,其基本思想是:當關鍵字key的哈希地址p=H(key)出現衝突時,以p爲基礎,產生另外一個哈希地址p1,若是p1仍然衝突,再以p爲基礎,產生另外一個哈希地址p2,…,直到找出一個不衝突的哈希地址pi ,將相應元素存入其中。這種方法有一個通用的再散列函數形式:

          Hi=(H(key)+di)% m   i=1,2,…,n

其中H(key)爲哈希函數,m 爲表長,di稱爲增量序列。增量序列的取值方式不一樣,相應的再散列方式也不一樣。主要有如下三種:

l         線性探測再散列

    dii=1,2,3,…,m-1

這種方法的特色是:衝突發生時,順序查看錶中下一單元,直到找出一個空單元或查遍全表。

l         二次探測再散列

    di=12,-12,22,-22,…,k2,-k2    ( k<=m/2 )

這種方法的特色是:衝突發生時,在表的左右進行跳躍式探測,比較靈活。

l        僞隨機探測再散列

    di=僞隨機數序列。

二、再哈希法

這種方法是同時構造多個不一樣的哈希函數:

    Hi=RH1(key)  i=1,2,…,k

當哈希地址Hi=RH1(key)發生衝突時,再計算Hi=RH2(key)……,直到衝突再也不產生。這種方法不易產生彙集,但增長了計算時間。

三、鏈地址法

這種方法的基本思想是將全部哈希地址爲i的元素構成一個稱爲同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,於是查找、插入和刪除主要在同義詞鏈中進行。鏈地址法適用於常常進行插入和刪除的狀況。

四、創建公共溢出區

這種方法的基本思想是:將哈希表分爲基本表溢出表兩部分,凡是和基本表發生衝突的元素,一概填入溢出表

97. 類加載的方式

1.經過new

2.經過反射利用當前線程的classloader

3.本身繼承實現一個classloader實現本身的類裝載器

class.forName Classloader.loadClass區別

Classloader

104.HashMap內部是怎麼實現的?(拉鍊式結構)

98. 核心:hashMap採用拉鍊法,構成「鏈表的數組」

存儲示意圖:

99. 索引index創建規則:

1)通常狀況下經過hash(key)%length實現,元素存儲在數組中的索引是由key的哈希值對數組的長度取模獲得。

2)hashmap也是一個線性的數組實現的,裏面定義一個內部類Entry,屬性包括key、value、next.Hashmap的基礎就是一個線性數組,該數組爲Entry[] ,map裏面的內容都保存在entry[]數組中。

(3)肯定數組的index:hashcode%table.length

數組的下標index相同,可是不表示hashcode相同。

實現隨機存儲的方法:

// 存儲時:

int hash = key.hashCode(); // 這個hashCode方法這裏不詳述,只要理解每一個key的hash是一個固定的int值

int index = hash % Entry[].length;

Entry[index] = value;

 

// 取值時:

int hash = key.hashCode();

int index = hash % Entry[].length;

return Entry[index];

put方法的實現:

若是兩個key經過hash%Entry[].length獲得的index相同,會不會有覆蓋的危險?

這裏HashMap裏面用到鏈式數據結構的一個概念。上面咱們提到過Entry類裏面有一個next屬性,做用是指向下一個Entry。打個比方, 第一個鍵值對A進來,經過計算其key的hash獲得的index=0,記作:Entry[0] = A。一會後又進來一個鍵值對B,經過計算其index也等於0,如今怎麼辦?HashMap會這樣作:B.next = A,Entry[0] = B,若是又進來C,index也等於0,那麼C.next = B,Entry[0] = C;這樣咱們發現index=0的地方其實存取了A,B,C三個鍵值對,他們經過next這個屬性連接在一塊兒。因此疑問不用擔憂。也就是說數組中存儲的是最後插入的元素

get方法的實現:

先定位到數組元素,再遍歷該元素處的鏈表

table的大小:

table的初始的大小並非initialCapacity,是initialCapacity的2的n次冪

目的在於:當哈希表的容量超過默認的容量時,必須從新調整table的大小,當容量已經達到最大的可能的值時,這時須要建立一張新的表,將原來的表映射到該新表。

req.getSession().invalidate(); 銷燬session

req.getSession().setMaxInactiveInterval(30); 設置默認session的過時時間,tomcat的默認過時時間是 30分鐘

100. 利用線程池的優點:

1下降資源消耗。經過重複利用已建立的線程下降線程建立和銷燬形成的消耗。

二、提升響應速度。當任務到達時,任務能夠不須要等到線程建立就能當即執行。

三、提升線程的可管理性。線程是稀缺資源,若是無限制的建立,不只會消耗系統資源,還會下降系統的穩定性,使用線程池能夠進行統一的分配,調優和監控。

boolean 單獨使用的時候還會被變成int,4個字節

boolean[] 數組使用的時候變成byte,1個字節

101. CacheBuffer的區別

Cache:緩存區,位於cpu和主內存之間容量很小但速度很快的存儲器,由於CPU的速度遠遠高於主內存的速度,CPU從內存中讀取數據許要等待很長的時間,而Cache保存着CPU剛用過的數據或循環使用的部分數據,Cache讀取數據更快,減小cpu等待時間。

Buffer:緩衝區,用於存儲速度不一樣步的狀況,處理系統兩端速度平衡,爲了減少短時間內突發I/O的影響,起到流量整形的做用。速度慢的能夠先把數據放到buffer,而後達到必定程度在讀取數據

內鏈接:

必須兩個表互相匹配纔會出現

外連接

左外連接:左邊不加限制

右外鏈接:右邊不加限制

全鏈接:左右都不加限制

102. 如何建立索引

全文檢索的索引建立過程通常有如下幾步:

第一步:一些要索引的原文檔(Document)

爲了方便說明索引建立過程,這裏特地用兩個文件爲例:

文件一:Students should be allowed to go out with their friends, but not allowed to drink beer.

文件二:My friend Jerry went to school to see his students but found them drunk which is not allowed.

第二步:將原文檔傳給分詞器(Tokenizer)

分詞器(Tokenizer)會作如下幾件事情(此過程稱爲Tokenize)

1. 將文檔分紅一個一個單獨的單詞。

2. 去除標點符號。

3. 去除停詞(Stop word)

所謂停詞(Stop word)就是一種語言中最普通的一些單詞,因爲沒有特別的意義,於是大多數狀況下不能成爲搜索的關鍵詞,於是建立索引時,這種詞會被去掉而減小索引的大小。

英語中停詞(Stop word)如:「the」,「a」,「this」等。

對於每一種語言的分詞組件(Tokenizer),都有一個停詞(stop word)集合。

通過分詞(Tokenizer)後獲得的結果稱爲詞元(Token)

在咱們的例子中,便獲得如下詞元(Token):

「Students」,「allowed」,「go」,「their」,「friends」,「allowed」,「drink」,「beer」,「My」,「friend」,「Jerry」,「went」,「school」,「see」,「his」,「students」,「found」,「them」,「drunk」,「allowed」。

第三步:將獲得的詞元(Token)傳給語言處理組件(Linguistic Processor)

語言處理組件(linguistic processor)主要是對獲得的詞元(Token)作一些同語言相關的處理。

對於英語,語言處理組件(Linguistic Processor)通常作如下幾點:

1. 變爲小寫(Lowercase)

2. 將單詞縮減爲詞根形式,如「cars」「car」等。這種操做稱爲:stemming

3. 將單詞轉變爲詞根形式,如「drove」「drive」等。這種操做稱爲:lemmatization

並且在此過程當中,咱們驚喜地發現,搜索「drive」,「driving」,「drove」,「driven」也可以被搜到。由於在咱們的索引 中,「driving」,「drove」,「driven」都會通過語言處理而變成「drive」,在搜索時,若是您輸入「driving」,輸入的查詢 語句一樣通過咱們這裏的一到三步,從而變爲查詢「drive」,從而能夠搜索到想要的文檔。

ZK實現分佈式鎖- 是否存在,而且最小的

根據ZK中節點是否存在,能夠做爲分佈式鎖的鎖狀態,以此來實現一個分佈式鎖,下面是分佈式鎖的基本邏輯:

客戶端調用create()方法建立名爲「/dlm-locks/lockname/lock-」的臨時順序節點。

客戶端調用getChildren(「lockname」)方法來獲取全部已經建立的子節點。

客戶端獲取到全部子節點path以後,若是發現本身在步驟1中建立的節點是全部節點中序號最小的,那麼就認爲這個客戶端得到了鎖。

若是建立的節點不是全部節點中須要最小的,那麼則監視比本身建立節點的序列號小的最大的節點,進入等待。直到下次監視的子節點變動的時候,再進行子節點的獲取,判斷是否獲取鎖。

並且zk的臨時節點能夠直接避免網絡斷開或主機宕機,鎖狀態沒法清除的問題,順序節點能夠避免驚羣效應。這些特性都使得利用ZK實現分佈式鎖成爲了最廣泛的方案之一。

Redus實現分佈式鎖,使用setNX (set if not exists)

getset(先寫新值返回舊值,用於分辨是否是首次操做) 防止網絡斷開後 會設置超時

http://blog.csdn.net/ugg/article/details/41894947

SETNX 能夠直接加鎖操做,好比說對某個關鍵詞foo加鎖,客戶端能夠嘗試

SETNX foo.lock

若是返回1,表示客戶端已經獲取鎖,能夠往下操做,操做完成後,經過

DEL foo.lock

命令來釋放鎖。

處理死鎖

在上面的處理方式中,若是獲取鎖的客戶端端執行時間過長,進程被kill掉,或者由於其餘異常崩潰,致使沒法釋放鎖,就會形成死鎖。因此,須要對加鎖要作時 效性檢測。所以,咱們在加鎖時,把當前時間戳做爲value存入此鎖中,經過當前時間戳和Redis中的時間戳進行對比,若是超過必定差值,認爲鎖已經時 效,防止鎖無限期的鎖下去,可是,在大併發狀況,若是同時檢測鎖失效,並簡單粗暴的刪除死鎖,再經過SETNX上鎖,可能會致使競爭條件的產生,即多個客 戶端同時獲取鎖。

C1獲取鎖,並崩潰。C2和C3調用SETNX上鎖返回0後,得到foo.lock的時間戳,經過比對時間戳,發現鎖超時。

C2 向foo.lock發送DEL命令。

C2 向foo.lock發送SETNX獲取鎖。

C3 向foo.lock發送DEL命令,此時C3發送DEL時,其實DEL掉的是C2的鎖。

C3 向foo.lock發送SETNX獲取鎖。

此時C2和C3都獲取了鎖,產生競爭條件,若是在更高併發的狀況,可能會有更多客戶端獲取鎖。因此,DEL鎖的操做,不能直接使用在鎖超時的狀況下,幸虧咱們有GETSET方法,假設咱們如今有另一個客戶端C4,看看如何使用GETSET方式,避免這種狀況產生。

C1獲取鎖,並崩潰。C2和C3調用SETNX上鎖返回0後,調用GET命令得到foo.lock的時間戳T1,經過比對時間戳,發現鎖超時。

C4 向foo.lock發送GESET命令,

GETSET foo.lock

並獲得foo.lock中老的時間戳T2

若是T1=T2,說明C4得到時間戳。

若是T1!=T2,說明C4以前有另一個客戶端C5經過調用GETSET方式獲取了時間戳,C4未得到鎖。只能sleep下,進入下次循環中。

如今惟一的問題是,C4設置foo.lock的新時間戳,是否會對鎖產生影響。其實咱們能夠看到C4和C5執行的時間差值極小,而且寫入foo.lock中的都是有效時間錯,因此對鎖並無影響。

爲了讓這個鎖更增強壯,獲取鎖的客戶端,應該在調用關鍵業務時,再次調用GET方法獲取T1,和寫入的T0時間戳進行對比,以避免鎖因其餘狀況被執行DEL 外解開而不知。以上步驟和狀況,很容易從其餘參考資料中看到。客戶端處理和失敗的狀況很是複雜,不只僅是崩潰這麼簡單,還多是客戶端由於某些操做被阻塞 了至關長時間,緊接着 DEL 命令被嘗試執行(但這時鎖卻在另外的客戶端手上)。也可能由於處理不當,致使死鎖。還有可能由於sleep設置不合理,致使Redis在大併發下被壓垮。 最爲常見的問題還有

 AOF重寫帶有子進程副本保證安全

103. Java虛擬機Java內存結構,分區,每一個區放置什麼

程序計數器:(線程私有)當前線程所執行的字節碼的行號指示器,經過改變這個計數器的值來選取下一條須要執行的字節碼的指令,以程序中分支、循環和跳轉等流程的控制都離不開這個計數器的指示。

虛擬機棧:(線程私有),每一個方法在執行時都會建立一個棧楨,用於存儲局部變量表、操做數棧、動態連接和方法出口等信息。一個方法從調用到執行完成的過程,對應的棧楨在虛擬機棧的進出過程。當線程結束時,虛擬機棧中的數據會被自動的釋放。

局部變量表:基本數據類型、對象的引用、返回地址,局部變量表鎖須要的內存空間是在程序編譯時就已經會被肯定好的。

本地方法棧:(線程私有)虛擬機棧是爲執行java方法所服務的,而本地方法棧是爲了虛擬機使用到的本地方法鎖服務的。

堆區:(線程共享)java堆是被全部的線程所共享的一片區域,全部的對象的實例和數組都會在堆區盡心分配。java堆細分:新生代和老年代;也可能會劃分出多個線程鎖共享額分配緩衝區TLAB;

Java堆能夠在物理上不連續的內存空間中,只要邏輯上連續就能夠。

方法區:(線程共享)存儲已經被虛擬機加載過的類的信息、常量、靜態變量和及時編譯器編譯後的代碼。在方法區中一個區域叫作:運行時常量池,用於存放編譯後生成的字面量和符號的引用。

堆的分代

(1)年輕代:

全部新生成的對象首先都是放在年輕代的。年輕代的目標就是儘量快速的收集掉那些生命週期短的對象。年輕代分三個區。一個Eden區,兩個Survivor區(通常而言)。

大部分對象在Eden區中生成。當Eden區滿時,還存活的對象將被複制到Survivor區(兩個中的一個),當一個Survivor區滿時,此區的存活對象將被複制到另一個Survivor區,當另外一個Survivor區也滿了的時候,從前一個Survivor區複製過來的而且此時還存活的對象,將被複制「年老區(Tenured)」。

(2)年老代:

在年輕代中經歷了N(可配置)次垃圾回收後仍然存活的對象,就會被放到年老代中。所以,能夠認爲年老代中存放的都是一些生命週期較長的對象。

(3)持久代:

用於存放靜態數據,如 Java Class, Method 等。持久代對垃圾回收沒有顯著影響。

104. OOM異常的處理思路

對象的建立方法,對象的內存的分配,對象的訪問定位

對象的建立:

(1)第一步,當遇到一個new的指令,首先去檢查這個指令的參數是否能在常量池中定位到一個類的符號引用,並檢查這個符號引用表明的類是否已經被加載、解析和初始化過。若是沒有,須要先執行相應的類加載過程;

(2)第二步,根據類加載完成後肯定的內存大小,爲對象分配內存;

(3)第三步,須要對分配到的內存空間都初始化爲零值;

(4)第四步,虛擬機要對對象設置一些基本信息,如對象是那個類的實例、對象的哈希碼、對象的GC分代年齡信息、如何才能找到類的元數據信息等,到這裏虛擬機建立對象的工做已經完成;

(5)第五步,從程序的角度,咱們還須要對對象進行初始化操做。

對象的內存分配:

(1)對象頭:

存儲hashcode 、gc分代年齡以及一些必要的自身的運行時數據

(2)實例數據:

存儲真實的數據信息

(3)對齊填充:

僅僅起到佔位符的做用

對象的訪問定位:

經過句柄池的訪問,在句柄池中保存着到對象實例數據的指針以及到對象類型的數據的指針

經過直接的指針服訪問,經過引用直接指向java堆的對象的實例數據

105. GC的三種收集方法:標記清除、標記整理、複製算法的原理與特色,分別用在什麼地方,若是讓你優化收集方法,有什麼思路?

標記清除法:

就是先標記哪些對象實例不用,而後直接清除。缺點就是產生大量的內存碎片,下次若要存儲一個大的對象,沒法找到連續內存而又必須提早GC

標記整理:

也就是先標記,而後對存活的對象進行移動,所有移動到一端,而後再對其它的內存進行清理。

複製算法:

把內存分紅相等的AB兩塊,每次只使用其中的一塊。好比當A內存使用完後,就把A中還存活着的對象複製到另一塊內存中去(B),而後再把已經使用過的內存清理掉。優勢:這樣就不用考慮內存碎片的問題了。缺點:內存減半,代價略高。

106. GC收集器有哪些?CMS收集器與G1收集器的特色。

對於新生代的收集器:

Serial單線程收集器 parnew多線程收集器  parallelSccavenge收集器

對於老年代的收集器:

CMS併發收集低停頓收集器  serial Old單線程收集器  parallel Old多線程收集器

107. CMS收集器:

優勢:併發收集、低停頓

缺點:

(1)對cpu資源很是的敏感,在併發的階段雖然不會致使用戶的線程停頓,可是會因爲佔用一部分的線程致使應用程序變慢,總的吞吐量會下降;

(2)沒法去處理浮動垃圾;

(3)基於「標記-清除」算法的收集器,因此會出現碎片。

114G1收集器:

優勢:

(1)能充分利用cpu、多核的優點,使用多個cpu縮短停頓的時間;

(2)分代收集,不要其餘收集器的配合即可以獨立管理整個的GC堆;

(3)空間整合:總體基於「標記-清理」算法的實現,局部是基於「複製」算法的實現;

(4)能夠預測的停頓

108. Minor GCFull GC分別在何時發生?

Minor GC:新生代GC,當jvm沒法爲一個新的對象分配空間時會觸發

Full GC:整個堆空間的GC

109. 類加載的五個過程:加載、鏈接、初始化。

類的加載:將類的class文件讀入內存,並建立一個叫作java.lang.Class對象,當程序中使用任何類時,系統都會爲之創建一個java.lang.Class對象。

這些類的class文件的來源:

(1)從本地文件系統中加載class文件

(2)從jar包中加載class文件,好比jdbc編程時

(3)經過網絡加載class文件

(4)把一個java源文件動態編譯,並執行加載

鏈接:

(1)驗證:驗證階段用於檢驗被加載的類是否具備正確的內部結構,並和其餘的類協調一致

(2)準備:爲類的類變量分配內存,並去設置默認的值

(3)解析:將類的二進制數據中的符號引用替換成直接引用。

初始化:

主要是對類變量進行初始化。

(1)若是該類尚未被加載和鏈接,則先進行加載鏈接

(2)若是該類的直接父類尚未被初始化,則先初始化其直接父類

(3)類中若是有初始化的語句則先去執行這些初始化語句。

110. 反射

概念:在運行的狀態中,對於任何一個類或者對象,能夠知道其任意的方法和屬性,這種動態地調用其屬性和方法的手段叫作反射。利用的反編譯的手段

1、經過三種方式來獲取Employee類型,獲取類:

(1)Class c1 = Class.forName(「Employee」);

(2)Class c2 =Employee.class;

(3)Employee e = new Employee(); Class c3 = e.getClass();

2、獲得class的實例:

Object o = c1.newInstance();

3、獲取全部的屬性

Field[] fs = c.getDeclaredFields();  

4、獲取全部的方法

GetDeclareMethods();

動態代理

J2se多線程(線程鎖)

線程的狀態:

新建狀態、就緒狀態、運行狀態、阻塞狀態、死亡狀態(線程狀態轉換圖)

多線程的建立和啓動:

(1)繼承Thread類,重寫類的run方法,調用對象的start方法啓動

(2)實現Runnable接口,並重寫該接口的run方法,該方法一樣是線程的執行體,建立runnable實現類的實例,並以此實例做爲Thread類的target來建立thread對象,該thread對象纔是真的線程對象。

(3)使用Callable和Future接口建立線程。具體是建立Callable接口的實現類,並實現clall()方法。並使用FutureTask類來包裝Callable實現類的對象,且以此FutureTask對象做爲Thread對象的target來建立線程。

方法3:

// 建立MyCallable對象

Callable myCallable = new MyCallable();

//使用FutureTask來包裝MyCallable對象

FutureTask ft = new FutureTask(myCallable);

//FutureTask對象做爲Thread對象的target

Thread thread = new Thread(ft);

//線程進入到就緒狀態

thread.start();   

線程同步的方法:sychronizedlockreentrantLock

synchronized修飾同步監視器:修飾可能被併發訪問的共享資源充當同步監視器;

synchronized修飾方法,同步方法的同步監視器是this,也就是調用該方法的對象;

synchronizedd能夠用來修飾方法,能夠修飾代碼塊,可是不能修飾構造器和成員變量;

使用lock鎖對象,每次只能有一個線程對lock對象進行加鎖和釋放鎖,線程開始訪問該鎖對象時必須先得到鎖lock

基本用法:

Private final ReentrantLock lock = new ReentrantLock();

Lock.lock();

Try(){

}catch(Exception e){

}finally{}

Lock.unlock();

鎖的等級:內置鎖、對象鎖、類鎖、方法鎖。

內置鎖:每個java對象均可以用作一個實現同步的鎖,這個鎖成爲內置鎖。當一個線程進入同步代碼塊或者方法的時候會自動得到該鎖,在退出同步代碼塊或者方法時會釋放該鎖。

得到內置鎖的方法:進入這個鎖的保護的同步代碼塊或者方法

注意:java內置鎖是一個互斥鎖,最多隻有一個線程可以得到該鎖。

對象鎖:對象鎖是用於對象實例方法,或者一個對象實例上的。

類鎖:類鎖用於類的靜態方法或者一個類的class對象上,一個類的對象實例有多個,可是每一個類只有一個class對象,即不一樣對象實例的對象鎖是互不干擾的,每個類都有一個類鎖。類鎖只是概念上的,並非真實存在的。

方法鎖:synchronized修飾方法,同步方法的同步監視器是this,也就是調用該方法的對象;

111. ThreadLocal的設計理念與做用。

做用:

ThreadLocal類只能去建立一個被線程訪問的變量,若是一段代碼含有一個ThreadLocal變量的引用,即便兩個線程同時執行這段代碼,它們也沒法訪問到對方的ThreadLocal變量。

建立ThreadLocal的方式:

private ThreadLocal myThreadLocal = new ThreadLocal();

咱們能夠看到,經過這段代碼實例化了一個ThreadLocal對象。

咱們只須要實例化對象一次,而且也不須要知道它是被哪一個線程實例化。

雖然全部的線程都能訪問到這個ThreadLocal實例,可是每一個線程卻只能訪問到本身經過調用ThreadLocal的set()方法設置的值。即便是兩個不一樣的線程在同一個ThreadLocal對象上設置了不一樣的值,他們仍然沒法訪問到對方的值。

如何爲ThreadLocal對象賦值和取值:

一旦建立了一個ThreadLocal變量,你能夠經過以下代碼設置某個須要保存的值:

myThreadLocal.set("A thread local value」);

能夠經過下面方法讀取保存在ThreadLocal變量中的值:

String threadLocalValue = (String) myThreadLocal.get();

get()方法返回一個Object對象,set()對象須要傳入一個Object類型的參數。

初始化該ThreadLocal變量:

經過建立一個ThreadLocal的子類重寫initialValue()方法,來爲一個ThreadLocal對象指定一個初始值。

112. ThreadPool用法與優點。

優點:

第一:下降資源消耗。經過重複利用已建立的線程下降線程建立和銷燬形成的消耗。

第二:提升響應速度。當任務到達時,任務能夠不須要等到線程建立就能當即執行。

第三:提升線程的可管理性。線程是稀缺資源,若是無限制的建立,不只會消耗系統資源,還會下降系統的穩定性,使用線程池能夠進行統一的分配,調優和監控。可是要作到合理的利用線程池,必須對其原理了如指掌。           

用法:

線程池的建立:

new  ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, milliseconds,runnableTaskQueue, handler);

參數:corePoolSize:線程池的基本大小

maximumPoolSize:線程池的最大大小

runnableTaskQueue:任務隊列

keepAliveTime:線程活動保持時間

執行方式:

threadsPool.execute(handler);

threadsPool.submit(handler);

線程池的關閉:

Shutdown和shutdownNow方法實現

線程池的工做流程分析:

先將任務提交的順序爲核心線程池、隊列、線程池、當這三個關節都不能執行用戶所提交的線程時,則拋出「沒法執行的任務」。     

113. 字節流和字符流

(1)java中字節流處理的最基本的單位是單個字節。一般用來處理二進制數據,最基本的兩個字節流類是InputStream和OutputStream,這兩個類都爲抽象類。

字節流在默認的狀況下是不支持緩存的。每次調用一次read方法都會請求操做系統來讀取一個字節,每每會伴隨一次磁盤的IO,若是要使用內存提升讀取的效率,應該使用BufferedInputStream。

(2)字符流處理的最基本的單元是unicode(碼元),一般用來來處理文本數據。

輸入字符流(文件到內存):把要讀取的字節序列按照指定的編碼方式解碼爲相應的字符序列,從而能夠存在內存中。

輸出字符流(內存到文件):把要寫入文件的字符序列轉爲指定的編碼方式下的字節序列,而後寫入文件中。

區別以下:

一、字節流操做的基本單元爲字節;字符流操做的基本單元爲Unicode碼元。

unicode的編碼範圍:0x0000~0XFFFF,在這個範圍的每一個數字都有一個字符與之對應

二、字節流默認不使用緩衝區;字符流使用緩衝區。

三、字節流一般用於處理二進制數據,實際上它能夠處理任意類型的數據,但它不支持直接寫入或讀取Unicode碼元;字符流一般處理文本數據,它支持寫入及讀取Unicode碼元。

114. 序列化(常見的序列化操做)

含義:

java序列化:將java對象轉換爲字節序列的過程;

java反序列化:將字節序列恢復爲java對象的過程

序列化的目的:

實現數據的持久化,將數據永久地保存在磁盤上,一般放在文件中;

利用序列化實現遠程的通信,在網絡上傳送對象的字節序列.

實現序列化的三種方法:

1)某實體類僅僅實現了serializable接口(經常使用)

序列化步驟:

步驟一:建立一個對象輸出流,它能夠包裝一個其它類型的目標輸出流,如文件輸出流:

ObjectOutputStream out = new ObjectOutputStream(new fileOutputStream(「D:\\objectfile.obj」));

步驟二:經過對象輸出流的writeObject()方法寫對象:

//Hello對象的字節流將輸入到文件

out.writeObject(「Hello」);

反序列化步驟:

步驟一:建立一個對象輸入流,它能夠包裝一個其它類型輸入流,如文件輸入流:

ObjectInputStream in = new ObjectInputStream(new fileInputStream(「D:\\objectfile.obj」));

步驟二:經過對象輸出流的readObject()方法讀取對象:

//將從文件中讀取到字節序列轉化爲對象

String obj1 = (String)in.readObject();

2)若實體類僅僅實現了Serializable接口,而且還定義了readObject(ObjectInputStream in)writeObject(ObjectOutputSteam out),則採用如下方式進行序列化與反序列化。

ObjectOutputStream調用該對象的writeObject(ObjectOutputStream out)的方法進行序列化。

ObjectInputStream會調用該對象的readObject(ObjectInputStream in)的方法進行反序列化。

3)若Student類實現了Externalnalizable接口,且Student類必須實現readExternal(ObjectInput in)writeExternal(ObjectOutput out)方法,則按照如下方式進行序列化與反序列化。

ObjectOutputStream調用Student對象的writeExternal(ObjectOutput out))的方法進行序列化。

ObjectInputStream會調用Student對象的readExternal(ObjectInput in)的方法進行反序列化。

115. String,StringBuffer,StringBuilder的區別,應用場景

1)在執行的速度上:StringBuilder>StringBuffer>String

2)String是字符串常量 StringBuffer和StringBuilder是字符串變量

例子1:

String s = 「abcd」;

s=s+1;

Syos(s);

底層執行:首先建立一個對象s,賦予abcd.而後又建立新的對象s,以前的對象並無發生變化,利用string操做字符串時,是在不斷建立新的對象,而原來的對象因爲沒有了引用,會被GC,這樣執行的效率會很低。

例子2:

String str2 = 「This is only a」;

String str3 = 「 simple」;

String str4 = 「 test」;

String str1 = str2 +str3 + str4;

同理:str2 str3 str3沒有被引用,可是建立了新的對象str1,執行速度上會很慢。

StringBuilder:線程非安全的

StringBuffer:線程安全的

例子3:

StringBuffer builder = new StringBuilder(「This is only a」).append(「 simple」).append(「 test」);

應用場景:

A:使用要操做少許的數據時,使用String

B:單線程操做字符串緩衝區下操做大量數據使用StringBulider

C:多線程操做字符串緩衝區下操做大量的數據使用StringBuffer

116. HashMapHashTable的區別

HashMap是線程不安全的;容許有null的鍵和值;執行的效率高一點;方法不是synchronize的要提供外同步;包含有containsvalue和containskey的方法

HashTable是線程安全的;不容許有null的鍵和值;效率稍微低些;方法是synchronize的;包含contains方法

117. GC垃圾回收機制原理

(參看博客)

118. ==與 equals區別

==:對於基本數據類型的變量,直接比較存儲的值是否相等;做用於引用類型的變量,則比較的是該變量所指向的地址是否相同。

equals:不一樣做用於基本數據類型的變量,若是沒有對equals方法進行重寫,則比較的是引用類型的變量所指向的對象的地址(至關於直接使用父類的equals方法,而該方法則是用==進行的比較,因此結果和用==比較的效果是同樣的);可是好比String Date類對equals進行了重寫,比較的是字面量。

119. final關鍵字

對於基本的數據類型,使用final關鍵字將使得數值恆定不變;

對於對象引用,final則是引用恆定不變,一但被初始化指向一個對象,它就不會再指向另一個對象,可是該對象自己是能夠被修改的;

對於類,若是不想繼承某個類,能夠將該類設置爲fianl形式,該類不會有子類;

對於方法,final修飾的方法不會被重寫

對於空白的final,對於沒有給定初始值的fianl,編譯器會在使用前初始化該final修飾的變量

對於宏變量:被final修飾的變量爲宏常量 在編譯的階段被其自己的值直接替換

short s1=1s1 s1+1

表達式類型的自動提高,一個short類型的變量和一個int型的數在一塊兒進行運算,會將short類型的數隱式轉換爲int參與運算,可是該運算的結果爲int類型是不一樣直接賦值給一個short類型的,必須進行強制的類型轉換,不然編譯是通不過的。

120. 八種基本數據類型的大小,以及他們的封裝類。

類型轉換:byte (1字節)--->short(1)/char(2)--->int(4)--->long(8)--->float(4)--->double(8)

分裝類:Byte Short Character Integer Long Float Double

121. Switch可否用string作參數?(分版本討論)

(1)在jdk1.7版本前不支持string做爲參數,僅僅支持byte、short、char,由於能夠轉換爲int,可是long和string不能轉換爲int,因此不能使用。

(2)在jdk1.7以後,支持使用string做爲case的參數,實際匹配的是該字符串的hash值,而後用equals進行安全性檢查。Switch支持String實際上是一個語法糖,在編譯後的字節碼文件中都會被還原成原生的類型,並在相應的位置插入強制轉換的代碼,底層的JVM在switch上並無修改;當傳入switch是null時,在運行時對一個null調用hashcode()方法,會拋出空指針異常。

122. Object有哪些公用方法?

object是全部類的父類,任何類都默認繼承Object類

九、Clone

private保護方法,實現對象的淺複製,只有類實現了Cloneable接口才能夠調用該方法,不然拋出CloneNotSupportException

十、Equals

在object中與==是同樣的,子類通常須要重寫該方法

十一、hashCode

該方法用於哈希查找,重寫了equals方法通常都要重寫hashcode方法,這個方法在一些具備哈希功能的collection中使用

十二、getClass

final方法,得到運行時的類型

1三、wait方法

使得當前的線程等待該對象的鎖,當前線程必須是該對象的擁有者,也就是具備該對象的鎖。Wait方法會一直等待,直到得到鎖(到了睡眠的時間間隔也會喚醒本身)或者被中斷掉。

調用該方法,當前的線程會進入到睡眠的狀態,直到調用該對象的notify方法、notifyAll方法、調用interrupt中斷該線程,時間間隔到了。

1四、Notify

喚醒在該對象上的等待的某個線程

1五、notifyAll

喚醒在該對象上的等待到全部的線程

1六、toString

把對象轉換成string類型進行輸出

123. Java的四種引用,強弱軟虛,用到的場景。

引用的級別:

強引用>軟引用>弱引用>虛引用

強引用:若是一個對象具備強引用,垃圾回收器絕對不會回收它。當內存空間不足時,jvm寧願拋出outofmemoryError,使得程序的異常終止。

軟引用:若是一個對象具備軟引用,則內存空間足夠,垃圾回收機制就不會去回收它,當內存不足時,就會進行回收。若是軟引用所引用的對象被垃圾回收器回收,java虛擬機就會把這個軟引用加入到與之關聯的引用隊列。

應用場景:實現內存敏感的高速緩存

弱引用:在垃圾回收器線程掃描它所管轄的內存區域的過程當中,一旦發現了只具備弱引用的對象,無論當前內存空間足夠與否,都會回收它的內存。

應用場景:gc運行後終止

虛引用:就是形同虛設,與其餘幾種引用都不一樣,虛引用並不會決定對象的生命週期。若是一個對象僅持有虛引用,那麼它就和沒有任何引用同樣,在任什麼時候候均可能被垃圾回收器回收。

124. 寫出生產者消費者模式。

125. Hashcode的做用。

(1)Hashcode 的存在主要用於解決查找的快捷性,好比在hashmap、hashtable中,hashcode是用來在散列的存儲結構中肯定對象的存儲的位置的。

(2)若是兩個對象相同,就是經過equals方法比較返回true,兩個對象裝在一個桶裏,也就是hashcode也要必定相同。

(3)兩個對象的hashcode相同,並不必定表明兩個對象就是相同的,只能說明他們存儲在一個桶裏。

(4)通常重寫了equals方法,也儘可能去重寫hashcode方法,保證先找到該桶,再去找到對應的類,經過equals方法進行比較。

126. ArrayListLinkedListVector的區別。

1ArrayList:是基於動態數組的數據結構,LinkedList的基於鏈表的數據結構

二、對於隨機訪問get和set,ArrayList性能較好,由於LinkedList會去移動指針

三、對於新增和刪除的操做,linkedList只須要修改指針的指向,性能較好,可是arrayList會移動數據。

vector的特色:

一、vector的方法都是線程同步的,是線程安全的,可是arraylist和linkedlist不是,因爲線程的同步必然會影響性能,因此vector的性能不過高。

二、當vector或者arraylist的元素超過它的初始的大小時,vector會將容量翻倍,可是arraylist只會增長50%,這樣有利於節約內存的空間。

127. MapSetListQueueStack的特色與用法。

128. HashMapConcurrentHashMap的區別

hashMap不是線程安全的;

concurrentHashMap是線程安全的;在其中引入了「分段鎖」,而不是將全部的方法加上synchronized,由於那樣就變成了hashtable.

所謂「分段鎖」,就是把一個大的Map拆分紅N個小的hashtable,根據key.hashcode()決定把key放在哪個hashtable中。

經過把整個Map分爲N個Segment(相似HashTable),能夠提供相同的線程安全,可是效率提高N倍,默認提高16倍。

129. TreeMapHashMapLindedHashMap的區別。

HashMap:根據鍵的hashcode值進行存儲數據,根據鍵能夠直接獲取它的值,具備快速訪問的特色,遍歷時取得數據是隨機的,hashmap最多隻容許一條記錄的鍵爲null(set無序不重複),容許多條記錄的值爲Null;若是要保證線程的同步,應該使用Collections.synchronizedMap()方法進行包裝,或者使用ConcurrentHashMap

LinkedHashMap:保存了記錄的插入的順序,在迭代遍歷Linkedhashmap時,先獲得的記錄確定是先插入的,它遍歷的速度只和實際的數據有關和容量沒關。

TreeMap:實現的是SortMap,可以把保存的記錄按照鍵進行排序,默認會按照鍵值的升序進行排序,當遍歷TreeMap時獲得的記錄是排序事後的。

Collection包結構,與Collections的區別。

Collection是一個集合的接口,提供了對集合對象進行操做的通用的方法。

在它下面的子接口:set、list、map

java.util.Collections是一個包裝的類,包含有各類的有關集合操做的靜態方法,好比包含對集合的搜索、排序、線程安全化等一系列的操做,此類不能被實例化,至關因而操做集合的工具類,服務於java的collection的框架。

介紹下Concurrent

concurrent包基本有3個package組成

(1)java.util.concurrent:提供大部分關於併發的接口和類,如BlockingQueue,Callable,ConcurrentHashMap,ExecutorService, Semaphore等

 

(2)java.util.concurrent.atomic:提供全部原子操做的類,如AtomicInteger, AtomicLong等;

 

(3)java.util.concurrent.locks:提供鎖相關的類, 如Lock, ReentrantLock, ReadWriteLock, Condition等;

concurrent包的優勢:

1. 首先,功能很是豐富,諸如線程池(ThreadPoolExecutor),CountDownLatch等併發編程中須要的類已經有現成的實現,不須要本身去實現一套;畢竟jdk1.4對多線程編程的主要支持幾乎就只有Thread, Runnable,synchronized等

2. concurrent包裏面的一些操做是基於硬件級別的CAS(compare and swap),就是在cpu級別提供了原子操做,簡單的說就能夠提供無阻塞、無鎖定的算法;而現代cpu大部分都是支持這樣的算法的;

Try-catch -finallytry裏有returnfinally還執行麼?

任然會執行。

一、無論有木有出現異常,finally塊中代碼都會執行;

 

二、當try和catch中有return時,finally仍然會執行;

 

三、finally是在return後面的表達式運算後執行的(此時並無返回運算後的值,而是先把要返回的值保存起來,無論finally中的代碼怎麼樣,返回的值都不會改變,任然是以前保存的值),因此函數返回值是在finally執行前肯定的;

 

四、finally中最好不要包含return,不然程序會提早退出,返回值不是try或catch中保存的返回值。

130. ExcptionError包結構。OOM你遇到過哪些狀況,SOF你遇到過哪些狀況。

131. Java面向對象的三個特徵與含義。

封裝:

是指將某事物的屬性和行爲包裝到對象中,這個對象只對外公佈須要公開的屬性和行爲,而這個公佈也是能夠有選擇性的公佈給其它對象。在Java中能使用private、protected、public三種修飾符或不用(即默認defalut)對外部對象訪問該對象的屬性和行爲進行限制。

繼承:

是子對象能夠繼承父對象的屬性和行爲,亦即父對象擁有的屬性和行爲,其子對象也就擁有了這些屬性和行爲。

多態:

java的引用變量有兩種類型,一個是編譯時的類型,一個是運行時的類型,編譯時類型由申明該變量時的類型決定,運行時的類型由實際賦值給該變量的對象所決定,若是編譯時的類型和運行時的類型不一致就可能出現所謂的多態。

在java中把一個子類的對象直接賦值給一個父類的引用變量,當運行該引用變量的方法時,其方法行爲老是表現出子類方法的行爲特徵,這就有可能出現,相同類型的變量,調用同一個方法時呈現多種不一樣的行爲特徵,出現了「多態」

132. OverrideOverload的含義和區別。

Overload:方法重載,在同一個類中,方法名相同,參數列表不一樣,至於方法的修飾符,反回值的類型,與方法的重載沒有任何的聯繫。

Override:方法重寫,兩同兩小一大

兩同:方法名稱相同、參數列表相同

兩小:返回值類型要小或者相等;拋出的異常要小或者相等

一大:子類方法的訪問權限要相等或者更大

133. Interfaceabstract類的區別。

實例化:

都不能被實例化

類:一個類只能繼承一次abstract類;一個類能夠實現多個interface

數據成員:能夠有本身的;接口的數據成員必須定義成static final的

方法:能夠有私有的,非abstract方法必須實現;接口中不能夠有私有的方法,默認都是public abstract的

變量:能夠有私有的,其值能夠在子類中從新定義,也能夠從新賦值;接口中不能夠有私有的成員變量,默認是public static final 實現類中不能去從新定義和改變其值

134. Java IONIO

IO是面向流的,NIO是面向緩衝區

Java NIO和IO之間第一個最大的區別是,IO是面向流的,NIO是面向緩衝區的。 Java IO面向流意味着每次從流中讀一個或多個字節,直至讀取全部字節,它們沒有被緩存在任何地方。此外,它不能先後移動流中的數據。若是須要先後移動從流中讀取的數據,須要先將它緩存到一個緩衝區。 Java NIO的緩衝導向方法略有不一樣。數據讀取到一個它稍後處理的緩衝區,須要時可在緩衝區中先後移動。這就增長了處理過程當中的靈活性。可是,還須要檢查是否該緩衝區中包含全部您須要處理的數據。並且,需確保當更多的數據讀入緩衝區時,不要覆蓋緩衝區裏還沒有處理的數據。

阻塞與非阻塞IO

Java IO的各類流是阻塞的。這意味着,當一個線程調用read() write()時,該線程被阻塞,直到有一些數據被讀取,或數據徹底寫入。該線程在此期間不能再幹任何事情了。 Java NIO的非阻塞模式,使一個線程從某通道發送請求讀取數據,可是它僅能獲得目前可用的數據,若是目前沒有數據可用時,就什麼都不會獲取。而不是保持線程阻塞,因此直至數據變的能夠讀取以前,該線程能夠繼續作其餘的事情。非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不須要等待它徹底寫入,這個線程同時能夠去作別的事情。線程一般將非阻塞IO的空閒時間用於在其它通道上執行IO操做,因此一個單獨的線程如今能夠管理多個輸入和輸出通道(channel)。

選擇器(Selectors)

Java NIO的選擇器容許一個單獨的線程來監視多個輸入通道,你能夠註冊多個通道使用一個選擇器,而後使用一個單獨的線程來「選擇」通道:這些通道里已經有能夠處理的輸入,或者選擇已準備寫入的通道。這種選擇機制,使得一個單獨的線程很容易來管理多個通道。

反射的做用原理。

見博客

135. wait()sleep()的區別。

(1)sleep方法,該方法屬於thread類;wait方法屬於object類

(2)sleep方法致使程序會暫停執行指定的時間,讓出cpu給其餘的線程,可是他仍是監控狀態的保持者,當到達指定的時間又會自動恢復運行。也就是調用sleep方法線程不會釋放對象鎖;調用wait方法會釋放對象鎖,進入到等待此對象的等待鎖定池,只有當針對此對象調用了notify()方法後,纔會獲取對象鎖進入運行的狀態。

136. foreach與正常for循環效率對比。

For循環能夠從前向後遍歷,也能夠從後向前遍歷,能夠不逐個遍歷,一般用於已知次數的循環。

foreach循環不能向迭代變量賦值,一般對集合對象從頭到位進行讀取,其有優化的存在。

137. JavaC++對比。

一、指針

java語言不提供指針,增長了自動的內存管理,有效的防止c/c++中的指針操做失誤。

二、多重繼承

C++支持多重繼承,java不支持多重繼承,可是容許實現多個接口。

三、數據類型和類

java將數據和方法結合起來,分裝到類中,每一個對象均可以實現本身的特色和方法;而c++容許將函數和變量定義全局的。

四、內存管理

java能夠對全部的對象進行內存管理,自動回收再也不使用的對象的內存;c++必須由程序員顯式分配內存釋放內存。

五、操做符的重載

C++支持操做符的重載,java不容許進行操做符的重載。

六、預處理功能

java不支持預處理功能,c++有一個預編譯的階段,也就是預處理器。

七、字符串

C++不支持字符串,java中支持字符串,是java的類對象。

八、數組

java引入了真正的數組,不一樣於c++中利用指針實現的僞數組。

九、類型的轉換

C++中有時會出現數據類型的隱含轉換,設計到自動強制類型的轉換問題,好比存在將浮點數直接轉換爲整數的狀況,java不支持自動的強制類型轉換,若是須要,必須顯示進行強制的類型轉換。

十、異常

java中使用try{}catch(){}finally{}進行異常的處理,c++沒有。

138. HTTPHTTPS的區別

https:是http的安全版本,利用ssl能夠對所傳輸的數據進行加密,默認端口是443

139. cookiesession的區別

(1)cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。 

(2)cookie不是很安全,別人能夠分析存放在本地的COOKIE並進行COOKIE欺騙,若是主要考慮到安全應當使用session 

(3)session會在必定時間內保存在服務器上。當訪問增多,會比較佔用你服務器的性能,若是主要考慮到減輕服務器性能方面,應當使用COOKIE 

(4)單個cookie在客戶端的限制是4K,就是說一個站點在客戶端存放的COOKIE不能4K。

(5)因此:將登錄信息等重要信息存放爲SESSION;其餘信息若是須要保留,能夠放在COOKIE中

140. 網路TCP三次握手、四次揮手,各個狀態的名稱和含義timewait的做用?

ACK:tcp協議規定,只有ack=1時纔有效,在鏈接創建後全部發送的豹紋的ack=1

Syn(SYNchronization):在鏈接創建時用來同步序號。

當SYN=1而ACK=0:這是一個鏈接請求報文;

當對方贊成創建鏈接時,則應該使得SYN=1並且ACK=1;

當SYN=1:這是一個鏈接請求或者鏈接接受報文

FIN(finis):終結的意思,用來釋放一個鏈接。當fin=1,表示次報文段的發送方的數據已經發送完畢並要求釋放鏈接。

A的狀態:關閉狀態--->同步已發送--->已創建

B的狀態:關閉狀態--->監聽狀態--->同步收到--->已創建

A:創建狀態--->終止等待1--->終止等待2--->等待2MSL

B:創建狀態--->關閉等待--->最後確認

Timewait的做用?

(1)爲了保證A發送最後一個ACK報文能到達B,由於這個ACK報文有可能會丟失,這樣會使得處在最後確認階段的B收不到已經發送的FIN+ACK的確認信息,B會超時重傳該報文段,在2MSL的時間內,A會收到信息,重傳依次確認,重啓該計時器。

(2)保證在2MSL的時間內,全部在本網絡上產生的報文段都消失,使得在新的鏈接中不會出現舊的鏈接請求的報文段。

2)SYN攻擊防範

141. TCP/IP層次架構,每層的做用和協議

OSI模型:應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層

TCP/IP模型:應用層、傳輸層、網絡互聯層、主機到網絡層

協議:

(1)應用層:FTP、TELNET、HTTP | SNMP、TFTP、NTP

將OSI模型的會話層和表示層整合成應用層,應用層面向不一樣的網絡應用引入了不一樣的應用層協議。

(2)傳輸層:TCP|UDP

功能是使得源端主機和目標端主機上的對等實體能夠進行會話,定義了兩種服務質量不一樣的協議,分別是TCP和UDP協議。

TCP協議是一個面向鏈接的、可靠的協議。它將一臺主機發出的字節流無差錯地發往互聯網上的其餘主機。在發送端,它負責把上層傳送下來的字節流分紅報文段並傳遞給下層。在接收端,它負責把收到的報文進行重組後遞交給上層。TCP協議還要處理端到端的流量控制,以免緩慢接收的接收方沒有足夠的緩衝區接收發送方發送的大量數據。  

UDP協議是一個不可靠的、無鏈接協議。主要適用於不須要對報文進行排序和流量控制的場合。

(3)網絡互聯層:IP

網絡互聯層是整個TCP/IP協議棧的核心。功能是把分組發往目標網絡或者主機。爲了儘快發送分組,可能會沿着不一樣的路徑同時進行分組傳遞。所以,分組到達的順序和發送的順序可能會不一致,這就須要上層必須對分組進行排序。同時它能夠將不一樣類型的網絡進行互聯,完成擁塞控制的功能。

(4)主機到網絡層:以太網、令牌環網、PPP

該層未被定義,具體的實現方式隨着網絡類型的不一樣而不一樣。

142. TCP擁塞控制

擁塞:計算機網絡中的帶寬、交換節點中的緩存和處理機都是網絡中的資源,當在某一個時間,對網絡中的某一個資源的需求超出了該資源所能提供的部分,網絡的性能會變壞,就出現了擁塞。

擁塞控制:防止過多的數據注入到網路,使得網絡中的路由器和鏈路不至於過載。擁塞控制是一個全局的過程,和流量控制不一樣,流量控制是點對點的通訊量的控制。

慢開始和擁塞避免:

發送方維持一個叫作擁塞窗口的狀態變量,擁塞窗口取決於網絡的擁塞程度,而且會動態的變化。發送方讓本身的發送窗口等於擁塞窗口,考慮接受方的接受能力,發送窗口可能會小於擁塞窗口。

慢開始算法:不要一開始就發送大量的數據,先探測下網絡的擁塞程度,由小到大逐漸增長擁塞窗口的數量。

擁塞避免算法:讓擁塞窗口緩慢增加,每進過一個往返時間就把發送方的擁塞窗口cwnd+1,而不是加倍,此時擁塞窗口按照線性的規律緩慢增加。

結合使用:爲了防止擁塞窗口增加過大引起網絡的擁塞,設置一個慢開始門限ssthresh狀態變量。其用法:

當cwnd使用慢開始算法

當cwnd>ssthresh,使用擁塞避免算法

當cwnd=ssthresh,慢開始算法和擁塞避免算法隨意。

當遇到網絡擁塞時,就把慢開始門限設置爲出現擁塞時發送窗口大小的一半,同時將擁塞的窗口設置爲1,再從新開始執行慢開始算法。

143. 滑動窗口是什麼設計的?

窗口:是一段能夠被髮送者發送的字節序列,其連續的範圍稱爲「窗口」

滑動:這段「容許發送的範圍」是隨着發送的過程而不斷變換的,表現的形式就是「按照順序滑動」

流量控制:

(1)TCP利用滑動窗口實現流量的控制機制

(2)如何考慮流量控制中的傳輸效率

流量控制,接受方傳遞信息給發送方,使其發送數據不要太快,是一種端到端的控制,主要的方式是返回的ack中會包含本身的接受的窗口的大小,發送方收到該窗口的大小時會控制本身的數據發送。

傳遞效率:單個發送字節單個確認,和窗口有一個空餘即通知發送方發送一個字節,會增長網絡中許多沒必要要的報文,由於會爲一個字節數據添加40個字節的頭部。

144. TCP/UDP的區別

一、TCP面向鏈接(如打電話要先撥號創建鏈接);UDP是無鏈接的,即發送數據以前不須要創建鏈接。

二、TCP提供可靠的服務。也就是說,經過TCP鏈接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付。

三、TCP面向字節流,其實是TCP把數據當作一連串無結構的字節流;UDP是面向報文的

UDP沒有擁塞控制,所以網絡出現擁塞不會使源主機的發送速率下降(對實時應用頗有用,如IP電話,實時視頻會議等)

四、每一條TCP鏈接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通訊

五、TCP首部開銷20字節;UDP的首部開銷小,只有8個字節

六、TCP的邏輯通訊信道是全雙工的可靠信道,UDP則是不可靠

145. TCP報文結構

緊急比特URG:URG=1,註解該報文應該儘快送達,而不須要按照原來的的隊列次序依次送達

確認比特ACK:只有當ACK=1,確認序號字段纔有意義

急迫比特PSH:當PSH=1時,註解懇求遠地TCP將本報文段當即傳送給應用層

復位比特RST:當註解呈現嚴重錯誤時,必須開釋鏈接,進行從新的傳輸鏈接

同步比特SYN:當SYN=1而ACK=0時,這是一個鏈接請求報文段,若對方同意鏈接請求會將SYN=1並且ACK=1

終止比特FIN:當FIN=1,註解字符串已經發送完畢,並請求開釋傳輸鏈接。

146. HTTP的報文結構(請求報文+響應報文)

HTTP請求報文:(1)請求行+(2)請求頭部+(3)請求正文

(1)請求行:請求方法+URL+協議版本

請求方法:經常使用GET、POST

協議版本:HTTP/主版本號.次版本號  經常使用HTTP/1.0和HTTP/1.1

(2)爲請求報文添加的一些附加的信息,「名/」組成,而且是每行一對 用冒號進行分割

在請求頭部存在空行,表示請求頭部的結束,接下來是請求正文!

區別get和post方式

對於get方式沒有請求的正文,對於post方式有請求的正文。

HTTP響應的報文格式:

(1)狀態行+(2)響應頭部+(3)響應正文

(1)狀態行:協議版本+狀態碼+狀態碼描述

(2)響應頭部:也是由鍵值對所組成

(3)響應正文,由服務器端接受數據

147. HTTP狀態碼的含義

148. http request的幾種類型(8種)

(1)OPTIONS:返回服務器針對特定資源所支持的HTTP請求方法。也能夠利用向Web服務器發送'*'的請求來測試服務器的功能性。

(2)HEAD:向服務器索要與GET請求相一致的響應,只不過響應體將不會被返回。這一方法能夠在沒必要傳輸整個響應內容的狀況下,就能夠獲取包含在響應消息頭中的元信息。

(3)GET:向特定的資源發出請求。

(4)POST:向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會致使新的資源的建立和/或已有資源的修改。

(5)PUT:向指定資源位置上傳其最新內容。

(6)DELETE:請求服務器刪除Request-URI所標識的資源。

(7)TRACE:回顯服務器收到的請求,主要用於測試或診斷。

(8)CONNECT:HTTP/1.1協議中預留給可以將鏈接改成管道方式的代理服務器。

GET方式和POST方式對比:

GET方式:請求數據放在HTTP包頭;使用明文傳送,不安全;長度較小,通常爲1024B;應用的場景爲查詢數據;若是傳送的是英文數字或者是數字,直接發送,若是傳送的是中文字符或則是其餘的字符,則會進行BASE64編碼

POST方式:請求數據放在HTTP正文;可明文或者密文傳送,較爲安全;長度通常沒有限制;應用在修改數據上。

149. http1.0 http1.1的區別

(1)HTTP1.0 規定瀏覽與服務器只是保持短暫的鏈接,瀏覽器每次請求都須要和服務器創建一個TCP鏈接,服務器完成請求處理後當即斷開TCP鏈接,服務器不去跟蹤每一個客戶也不去記錄每一個客戶過去的請求。HTTP1.0 不支持HOST請求字段

(2)HTTP1.1支持久鏈接,在一個TCP上能夠傳送多個HTTP請求和響應,減小了創建和關閉鏈接的消耗和延遲;

容許客戶端不用等待上一次請求的返回結果,就能夠去發送下一個請求,可是服務器端必須按照接受的客戶端請求的前後順序依次會送響應的結果,這樣客戶端纔可以區分出每次請求的響應的內容。

HTTP1.0 支持HOST請求字段,這樣就能夠使用一個IP地址和端口號,在此基礎上使用不一樣的主機名建立多個虛擬的WEB站點;

HTTP1.1 提供了與身份認證、狀態管理和cache緩存等機制

150. http怎麼去處理長鏈接

http1.1 默認支持長鏈接,即一次tcp鏈接,容許發送多個http請求。

當web服務器看到keep-alive值時,會創建長鏈接。

151. 電腦上訪問一個網頁的整個過程是怎樣的?DNSHTTPTCPOSPFIPARP

步驟1:當訪問www.baidu.com時,會先從本地的host文件中獲取該域名對應的IP地址,若是找不到就會用DNS協議來獲取IP,在該DNS協議中,計算機會由本地的DNS服務器來解析該域名,最終找到對應的IP地址。

步驟2:接下來是使用TCP協議,創建TCP鏈接,在創建鏈接以前須要,爲了將給服務器的消息帶給服務器,則須要OSPF\IP\ARP協議的支持,IP告訴該消息從哪裏出發,去向那裏;消息的傳送會通過一個個的路由器,OSPF會利用路由算法找出最佳的通往目的地址的路徑;ARP負責找到下一個節點的地址,ARP協議使用的MAC地址,整個的發送的過程涉及到每個節點的MAP地址。

步驟3:經過步驟2的解析IP,如今能夠和服務器創建TCP鏈接了,這時客戶端即可以將Http請求數據發送給服務器端。服務器端進行處理,而後以http response的形式發送給客戶端。

152. IP地址的分類

A類地址:1個字節的網絡號+3個字節的主機地址  0.0.0.0~126.255.255.255

B類地址:2個字節的網絡號+2個字節的主機地址  128.0.0.0~191.255.255.255

C類地址:3個字節的網絡號+1個字節的主機地址  192.0.0.0~223.255.255.255

D類地址:多播地址

E類地址:保留爲從此使用

153. 路由器和交換機的區別

交換機:爲數據楨從一個端口到另一個端口的轉發提供了低時延、低開銷的通路,使得任意端口接受的數據幀都可以從其餘的端口送出。

路由器:網絡鏈接和路由選擇,用於網絡層的數據轉發。

154. 如何設計一個高併發的系統?

① 數據庫的優化,包括合理的事務隔離級別、SQL語句優化、索引的優化

使用緩存,儘可能減小數據庫 IO

③ 分佈式數據庫、分佈式緩存

④ 服務器的負載均衡

155. 設計模式簡單工廠模式

有一個抽象的產品父類將全部的具體的產品抽象出來,達到複用的目的。同時有一個簡單工廠維護一個對抽象產品的依賴,在該簡單工廠中去負責實例的建立,在該工廠中去實例不一樣的對象,每每須要利用case判斷語句去動態實例化相關的類。

工廠方法模式

建立對象的接口,讓子類去決定具體實例化的對象,把簡單的內部邏輯的判斷,轉移到了客戶端,讓客戶端去動態地實例化相關的子類。工廠方法模式克服了簡單工廠違背開放-封閉原則的特色。

抽象工廠模式

提供建立一系列相關或者相互依賴對象的接口,而無需指定他們具體的類。

職責鏈模式

使得多個對象都有機會去處理請求,從而避免請求的發送者和接受者之間的耦合關係,將這些對象連成一條鏈,並沿着這條鏈去傳遞該請求,直到有一個對象處理它爲之。

單例模式

2)惡漢式的單例模式

利用靜態static的方式進行實例化,在類被加載時就會建立實例。

/**

 * 餓漢式實現單例模式

 */

public class Singleton {

  private static Singleton instance = new Singleton();

    private Singleton() {

    }

    public static Singleton getInstance() {

        return instance;

    }

}

(6)懶漢式實現單例模式

在被第一次引用時纔去建立對象。

/**

 * 懶漢式實現單例模式

 */

public class Singleton {

    private static Singleton instance;//建立私有的靜態變量

    private Singleton() {//私有的構造函數

    }

    // synchronized方法,多線程狀況下保證單例對象惟一

public static synchronized Singleton getInstance() {

//若是實例對象爲空,就從新去實例化

        if (instance == null) {

            instance = new Singleton();

        }

        return instance;

    }

}

分析:這中方法的實現,效率不高,由於該方法定義爲同步的方法。

(7)雙重鎖實現的單例模式

/**

 * DCL實現單例模式

 */

public class Singleton {

    private static Singleton instance = null;

    private Singleton() {

    }

    public static Singleton getInstance() {

        // 兩層判空,第一層是爲了不沒必要要的同步

        // 第二層是爲了在null的狀況下建立實例

        if (instance == null) {

            synchronized (Singleton.class) {

                if (instance == null) {

                    instance = new Singleton();

                }

            }

        }

        return instance;

    }

}

分析:資源的利用率較高,在須要的時候去初始化實例,並且能夠保證線程的安全,該方法沒有去進行同步鎖,效率比較好。

(8)靜態內部類實現單例模式

/**

 * 靜態內部類實現單例模式

 */

public class Singleton {

    private Singleton() {

}

//返回實例的方法

    public static Singleton getInstance() {

        return SingletonHolder.instance;

    }

    /**

     * 靜態內部類

     */

private static class SingletonHolder {

    //靜態私有的實例對象

        private static Singleton instance = new Singleton();

    }

}

分析:第一次加載類時不會去初始化instance,只有第一次調用getInstance()方法時,虛擬機纔會加載內部類,初始化instance

能夠保證線程的安全,單例對象的惟一,延遲了單例的初始化。

(9)枚舉單例

/**

 * 枚舉實現單例模式

 */

public enum SingletonEnum {

    INSTANCE;

    public void doSomething() {

        System.out.println("do something");

    }

}

分析:枚舉實例的建立是線程安全的,即便反序列化也不會生成新的實例,在任何的狀況下都是單例的。

適配器模式

將一個類的接口轉換成客戶但願的另一個接口,使得本來因爲接口步兼容而不能一塊兒工做的類變得能夠一塊兒工做。

target是咱們所指望的接口的類型,包含一個request方法,經過使用adapter去實現該接口,並實現其中的request方法,在adapter中創建一個私有的adaptee對象,在adapter重寫的方法中去調用specificRequest方法,這樣適配器adapter就構建好了。只須要在客戶端,建立adapter實例,調用request方法就能夠利用多態的方式,實現了specificRequest()方法。

觀察者模式

定義了一種一對多的依賴關係,讓多個觀察者能夠同時去監聽某一個主題對象,這個主題對象在狀態發生變化時,會通知全部的觀察者對象,使得他們可以自動更新本身。

Subject:把全部對觀察者對象的引用保存在一個彙集裏,每一個主題均可以有任何數量的觀察者,能夠增長刪除觀察者對象。

Observer:抽象觀察者,爲全部的具體的觀察者定義一個接口,在獲得主題時更新本身。

concreteObserver:具體的觀察者,實現更新的方法

concreteSubject:具體的主題

做用:應用在一個對象改變時,須要改變其餘的對象,並且具體不知道有多少個對象須要改變,將耦合的雙方都依賴於抽象而不是依賴於具體,從而使得各自的變化都不會影響到另一邊的變化。

大整數BigInteger  大浮點數 BigDecimal

java運算的優先級:優先級相同時比較結合性:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

java 高併發

156. 一、線程與進程

進程是一個實體。每個進程都有它本身的地址空間,通常狀況下,包括文本區域(text region)、數據區域(data region)和堆棧(stack region)。文本區域存儲處理器執行的代碼;數據區域存儲變量和進程執行期間使用的動態分配的內存;堆棧區域存儲着活動過程調用的指令和本地變量。

一個標準的線程由線程ID,當前指令指針(PC),寄存器集合和堆棧組成。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程本身不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的所有資源。

區別不一樣 
a,地址空間:進程內的一個執行單元;進程至少有一個線程;它們共享進程的地址空間;而進程有本身獨立的地址空間; 
b,資源擁有:進程是資源分配和擁有的單位,同一個進程內的線程共享進程的資 
c,線程是處理器調度的基本單位,但進程不是. 
d,兩者都可併發執行.

157. 二、 守護線程

Java中有兩類線程:用戶線程 (User Thread)、守護線程 (Daemon Thread)。 
守護線程和用戶線程的區別在於:守護線程依賴於建立它的線程,而用戶線程則不依賴。舉個簡單的例子:若是在main線程中建立了一個守護線程,當main方法運行完畢以後,守護線程也會隨着消亡。而用戶線程則不會,用戶線程會一直運行直到其運行完畢。在JVM中,像垃圾收集器線程就是守護線程。

158. 三、java thread狀態

NEW 狀態是指線程剛建立, 還沒有啓動

RUNNABLE 狀態是線程正在正常運行中, 固然可能會有某種耗時計算/IO等待的操做/CPU時間片切換等, 這個狀態下發生的等待通常是其餘系統資源, 而不是鎖, Sleep等

BLOCKED 這個狀態下, 是在多個線程有同步操做的場景, 好比正在等待另外一個線程的synchronized 塊的執行釋放, 也就是這裏是線程在等待進入臨界區

WAITING 這個狀態下是指線程擁有了某個鎖以後, 調用了他的wait方法, 等待其餘線程/鎖擁有者調用 notify / notifyAll 一遍該線程能夠繼續下一步操做, 這裏要區分 BLOCKED 和 WATING 的區別, 一個是在臨界點外面等待進入, 一個是在理解點裏面wait等待別人notify, 線程調用了join方法 join了另外的線程的時候, 也會進入WAITING狀態, 等待被他join的線程執行結束

TIMED_WAITING 這個狀態就是有限的(時間限制)的WAITING, 通常出如今調用wait(long), join(long)等狀況下, 另一個線程sleep後, 也會進入TIMED_WAITING狀態

TERMINATED 這個狀態下表示 該線程的run方法已經執行完畢了, 基本上就等於死亡了(當時若是線程被持久持有, 可能不會被回收)

159. 四、請說出與線程同步以及線程調度相關的方法。

wait():使一個線程處於等待(阻塞)狀態,而且釋放所持有的對象的鎖;

sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要處理InterruptedException異常;

notify():喚醒一個處於等待狀態的線程,固然在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM肯定喚醒哪一個線程,並且與優先級無關;

notityAll():喚醒全部處於等待狀態的線程,該方法並非將對象的鎖給全部線程,而是讓它們競爭,只有得到鎖的線程才能進入就緒狀態;

160. 五、進程調度算法

實時系統FIFO(First Input First Output,先進先出算法),SJF(Shortest Job First,最短做業優先算法),SRTF(Shortest Remaining Time First,最短剩餘時間優先算法)。 
交互式系統RR(Round Robin,時間片輪轉算法),HPF(Highest Priority First,最高優先級算法),多級隊列,最短進程優先,保證調度,彩票調度,公平分享調度。

161. 六、wait()和sleep()的區別

sleep來自Thread類,和wait來自Object類

調用sleep()方法的過程當中,線程不會釋放對象鎖。而 調用 wait 方法線程會釋放對象鎖

sleep睡眠後不出讓系統資源,wait讓出系統資源其餘線程能夠佔用CPU

sleep(milliseconds)須要指定一個睡眠時間,時間一到會自動喚醒

162. 七、ThreadLocal,以及死鎖分析

hreadLocal爲每一個線程維護一個本地變量。 
採用空間換時間,它用於線程間的數據隔離,爲每個使用該變量的線程提供一個副本,每一個線程均可以獨立地改變本身的副本,而不會和其餘線程的副本衝突。 
ThreadLocal類中維護一個Map,用於存儲每個線程的變量副本,Map中元素的鍵爲線程對象,而值爲對應線程的變量副本。 
完全理解ThreadLocal

163. 八、Synchronized 與Lock

ReentrantLock 擁有Synchronized相同的併發性和內存語義,此外還多了 鎖投票,定時鎖等候和中斷鎖等候 
線程A和B都要獲取對象O的鎖定,假設A獲取了對象O鎖,B將等待A釋放對O的鎖定, 
若是使用 synchronized ,若是A不釋放,B將一直等下去,不能被中斷 
若是 使用ReentrantLock,若是A不釋放,能夠使B在等待了足夠長的時間之後,中斷等待,而幹別的事情

ReentrantLock獲取鎖定與三種方式: 
a) lock(), 若是獲取了鎖當即返回,若是別的線程持有鎖,當前線程則一直處於休眠狀態,直到獲取鎖 
b) tryLock(), 若是獲取了鎖當即返回true,若是別的線程正持有鎖,當即返回false; 
c)tryLock(long timeout,TimeUnit unit), 若是獲取了鎖定當即返回true,若是別的線程正持有鎖,會等待參數給定的時間,在等待的過程當中,若是獲取了鎖定,就返回true,若是等待超時,返回false; 
d) lockInterruptibly:若是獲取了鎖定當即返回,若是沒有獲取鎖定,當前線程處於休眠狀態,直到或者鎖定,或者當前線程被別的線程中斷

整體的結論先擺出來:

synchronized: 
在資源競爭不是很激烈的狀況下,偶爾會有同步的情形下,synchronized是很合適的。緣由在於,編譯程序一般會盡量的進行優化synchronized,另外可讀性很是好,無論用沒用過5.0多線程包的程序員都能理解。 
ReentrantLock: 
ReentrantLock提供了多樣化的同步,好比有時間限制的同步,能夠被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在資源競爭不激烈的情形下,性能稍微比synchronized差點點。可是當同步很是激烈的時候,synchronized的性能一會兒能降低好幾十倍。而ReentrantLock確還能維持常態。

164. 九、Volatile和Synchronized

Volatile和Synchronized四個不一樣點:

粒度不一樣,前者針對變量 ,後者鎖對象和類

syn阻塞,volatile線程不阻塞

syn保證三大特性,volatile不保證原子性

syn編譯器優化,volatile不優化 
要使 volatile 變量提供理想的線程安全,必須同時知足下面兩個條件: 

對變量的寫操做不依賴於當前值。

該變量沒有包含在具備其餘變量的不變式中。

165. 十、CAS

CAS是樂觀鎖技術,當多個線程嘗試使用CAS同時更新同一個變量時,只有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程並不會被掛起,而是被告知此次競爭中失敗,並能夠再次嘗試。CAS有3個操做數,內存值V,舊的預期值A,要修改的新值B。當且僅當預期值A和內存值V相同時,將內存值V修改成B,不然什麼都不作。

166. 十一、Java中Unsafe類詳解

經過Unsafe類能夠分配內存,能夠釋放內存;類中提供的3個本地方法allocateMemory、reallocateMemory、freeMemory分別用於分配內存,擴充內存和釋放內存,與C語言中的3個方法對應。

能夠定位對象某字段的內存位置,也能夠修改對象的字段值,即便它是私有的;

掛起與恢復:將一個線程進行掛起是經過park方法實現的,調用 park後,線程將一直阻塞直到超時或者中斷等條件出現。unpark能夠終止一個掛起的線程,使其恢復正常。整個併發框架中對線程的掛起操做被封裝在 LockSupport類中,LockSupport類中有各類版本pack方法,但最終都調用了Unsafe.park()方法。

cas 
Java中Unsafe類詳解

167. 十二、線程池

線程池的做用: 
在程序啓動的時候就建立若干線程來響應處理,它們被稱爲線程池,裏面的線程叫工做線程 
第一:下降資源消耗。經過重複利用已建立的線程下降線程建立和銷燬形成的消耗。 
第二:提升響應速度。當任務到達時,任務能夠不須要等到線程建立就能當即執行。 
第三:提升線程的可管理性。 
經常使用線程池:ExecutorService 是主要的實現類,其中經常使用的有 
Executors.newSingleT 
hreadPool(),newFixedThreadPool(),newcachedTheadPool(),newScheduledThreadPool()。

168. 1三、ThreadPoolExecutor

構造方法參數說明

corePoolSize:核心線程數,默認狀況下核心線程會一直存活,即便處於閒置狀態也不會受存keepAliveTime限制。除非將allowCoreThreadTimeOut設置爲true。 
maximumPoolSize:線程池所能容納的最大線程數。超過這個數的線程將被阻塞。當任務隊列爲沒有設置大小的LinkedBlockingDeque時,這個值無效。 
keepAliveTime:非核心線程的閒置超時時間,超過這個時間就會被回收。 
unit:指定keepAliveTime的單位,如TimeUnit.SECONDS。當將allowCoreThreadTimeOut設置爲true時對corePoolSize生效。 
workQueue:線程池中的任務隊列. 
經常使用的有三種隊列,SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue。

threadFactory:線程工廠,提供建立新線程的功能。ThreadFactory是一個接口,只有一個方法

原理

若是當前池大小 poolSize 小於 corePoolSize ,則建立新線程執行任務。

若是當前池大小 poolSize 大於 corePoolSize ,且等待隊列未滿,則進入等待隊列

若是當前池大小 poolSize 大於 corePoolSize 且小於 maximumPoolSize ,且等待隊列已滿,則建立新線程執行任務。

若是當前池大小 poolSize 大於 corePoolSize 且大於 maximumPoolSize ,且等待隊列已滿,則調用拒絕策略來處理該任務。

線程池裏的每一個線程執行完任務後不會馬上退出,而是會去檢查下等待隊列裏是否還有線程任務須要執行,若是在 keepAliveTime 裏等不到新的任務了,那麼線程就會退出。

1三、Executor拒絕策略

AbortPolicy:爲java線程池默認的阻塞策略,不執行此任務,並且直接拋出一個運行時異常,切記ThreadPoolExecutor.execute須要try 
catch,不然程序會直接退出.

DiscardPolicy:直接拋棄,任務不執行,空方法

DiscardOldestPolicy:從隊列裏面拋棄head的一個任務,並再次execute 此task。

CallerRunsPolicy:在調用execute的線程裏面執行此command,會阻塞入

用戶自定義拒絕策略:實現RejectedExecutionHandler,並本身定義策略模式

169. 1四、CachedThreadPool 、 FixedThreadPool、SingleThreadPool

newSingleThreadExecutor :建立一個單線程化的線程池,它只會用惟一的工做線程來執行任務, 保證全部任務按照指定順序(FIFO, LIFO, 優先級)執行 
適用場景:任務少 ,而且不須要併發執行

newCachedThreadPool :建立一個可緩存線程池,若是線程池長度超過處理須要,可靈活回收空閒線程,若無可回收,則新建線程. 
線程沒有任務要執行時,便處於空閒狀態,處於空閒狀態的線程並不會被當即銷燬(會被緩存住),只有當空閒時間超出一段時間(默認爲60s)後,線程池纔會銷燬該線程(至關於清除過期的緩存)。新任務到達後,線程池首先會讓被緩存住的線程(空閒狀態)去執行任務,若是沒有可用線程(無空閒線程),便會建立新的線程。 
適用場景:處理任務速度 > 提交任務速度,耗時少的任務(避免無限新增線程)

newFixedThreadPool :建立一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。

newScheduledThreadPool:建立一個定長線程池,支持定時及週期性任務執行

170. 1五、CopyOnWriteArrayList

CopyOnWriteArrayList : 寫時加鎖,當添加一個元素的時候,將原來的容器進行copy,複製出一個新的容器,而後在新的容器裏面寫,寫完以後再將原容器的引用指向新的容器,而讀的時候是讀舊容器的數據,因此能夠進行併發的讀,但這是一種弱一致性的策略。 
使用場景:CopyOnWriteArrayList適合使用在讀操做遠遠大於寫操做的場景裏,好比緩存。

1六、AQS

AQS使用一個int成員變量來表示同步狀態,經過內置的FIFO隊列來完成獲取資源線程的排隊工做。

private volatile int state;//共享變量,使用volatile修飾保證線程可見性

1

2種同步方式:獨佔式,共享式。獨佔式如ReentrantLock,共享式如Semaphore,CountDownLatch,組合式的如ReentrantReadWriteLock

節點的狀態 
CANCELLED,值爲1,表示當前的線程被取消; 
SIGNAL,值爲-1,表示當前節點的後繼節點包含的線程須要運行,也就是unpark; 
CONDITION,值爲-2,表示當前節點在等待condition,也就是在condition隊列中; 
PROPAGATE,值爲-3,表示當前場景下後續的acquireShared可以得以執行; 
值爲0,表示當前節點在sync隊列中,等待着獲取鎖。

模板方法模式 
 protected boolean tryAcquire(int arg) : 獨佔式獲取同步狀態,試着獲取,成功返回true,反之爲false 
 protected boolean tryRelease(int arg) :獨佔式釋放同步狀態,等待中的其餘線程此時將有機會獲取到同步狀態; 
 protected int tryAcquireShared(int arg) :共享式獲取同步狀態,返回值大於等於0,表明獲取成功;反之獲取失敗; 
 protected boolean tryReleaseShared(int arg) :共享式釋放同步狀態,成功爲true,失敗爲false 
AQS維護一個共享資源state,經過內置的FIFO來完成獲取資源線程的排隊工做。該隊列由一個一個的Node結點組成,每一個Node結點維護一個prev引用和next引用,分別指向本身的前驅和後繼結點。雙端雙向鏈表。 

獨佔式:樂觀的併發策略 
acquire 
 a.首先tryAcquire獲取同步狀態,成功則直接返回;不然,進入下一環節; 
b.線程獲取同步狀態失敗,就構造一個結點,加入同步隊列中,這個過程要保證線程安全; 
 c.加入隊列中的結點線程進入自旋狀態,如果老二結點(即前驅結點爲頭結點),纔有機會嘗試去獲取同步狀態;不然,當其前驅結點的狀態爲SIGNAL,線程即可安心休息,進入阻塞狀態,直到被中斷或者被前驅結點喚醒。 
release 
release的同步狀態相對簡單,須要找到頭結點的後繼結點進行喚醒,若後繼結點爲空或處於CANCEL狀態,從後向前遍歷找尋一個正常的結點,喚醒其對應線程。

共享式
共享式地獲取同步狀態.同步狀態的方法tryAcquireShared返回值爲int。 
a.當返回值大於0時,表示獲取同步狀態成功,同時還有剩餘同步狀態可供其餘線程獲取; 
 b.當返回值等於0時,表示獲取同步狀態成功,但沒有可用同步狀態了; 
 c.當返回值小於0時,表示獲取同步狀態失敗。

AQS實現公平鎖和非公平鎖 
非公平鎖中,那些嘗試獲取鎖且還沒有進入等待隊列的線程會和等待隊列head結點的線程發生競爭。公平鎖中,在獲取鎖時,增長了isFirst(current)判斷,當且僅當,等待隊列爲空或當前線程是等待隊列的頭結點時,纔可嘗試獲取鎖。 
 Java併發包基石-AQS詳解

171. 1六、Java裏的阻塞隊列

7個阻塞隊列。分別是

ArrayBlockingQueue :一個由數組結構組成的有界阻塞隊列。 
LinkedBlockingQueue :一個由鏈表結構組成的有界阻塞隊列。 
PriorityBlockingQueue :一個支持優先級排序的無界阻塞隊列。 
DelayQueue:一個使用優先級隊列實現的無界阻塞隊列。 
SynchronousQueue:一個不存儲元素的阻塞隊列。 
LinkedTransferQueue:一個由鏈表結構組成的無界阻塞隊列。 
LinkedBlockingDeque:一個由鏈表結構組成的雙向阻塞隊列。

添加元素

Java中的阻塞隊列接口BlockingQueue繼承自Queue接口。BlockingQueue接口提供了3個添加元素方法。 
add:添加元素到隊列裏,添加成功返回true,因爲容量滿了添加失敗會拋出IllegalStateException異常 
offer:添加元素到隊列裏,添加成功返回true,添加失敗返回false 
put:添加元素到隊列裏,若是容量滿了會阻塞直到容量不滿

刪除方法

3個刪除方法 
poll:刪除隊列頭部元素,若是隊列爲空,返回null。不然返回元素。 
remove:基於對象找到對應的元素,並刪除。刪除成功返回true,不然返回false 
take:刪除隊列頭部元素,若是隊列爲空,一直阻塞到隊列有元素並刪除

172. 1七、condition

Condition的源碼理解,主要就是理解等待隊列,等待隊列能夠類比同步隊列,並且等待隊列比同步隊列要簡單,由於等待隊列是單向隊列,同步隊列是雙向隊列。

java condition使用及分

173. 1八、DelayQueue

隊列中每一個元素都有個過時時間,而且隊列是個優先級隊列,當從隊列獲取元素時候,只有過時元素纔會出隊列。

併發隊列-無界阻塞延遲隊列delayqueue原理探究

174. 1九、Fork/Join框架

 Fork/Join框架是Java 7提供的一個用於並行執行任務的框架,是一個把大任務分割成若干個小任務,最終彙總每一個小任務結果後獲得大任務結果的框架。Fork/Join框架要完成兩件事情:

  1.任務分割:首先Fork/Join框架須要把大的任務分割成足夠小的子任務,若是子任務比較大的話還要對子任務進行繼續分割

  2.執行任務併合並結果:分割的子任務分別放到雙端隊列裏,而後幾個啓動線程分別從雙端隊列裏獲取任務執行。子任務執行完的結果都放在另一個隊列裏,啓動一個線程從隊列裏取數據,而後合併這些數據。

  在Java的Fork/Join框架中,使用兩個類完成上述操做

  1.ForkJoinTask:咱們要使用Fork/Join框架,首先須要建立一個ForkJoin任務。該類提供了在任務中執行fork和join的機制。一般狀況下咱們不須要直接集成ForkJoinTask類,只須要繼承它的子類,Fork/Join框架提供了兩個子類:

    a.RecursiveAction:用於沒有返回結果的任務

    b.RecursiveTask:用於有返回結果的任務

  2.ForkJoinPool:ForkJoinTask須要經過ForkJoinPool來執行

  任務分割出的子任務會添加到當前工做線程所維護的雙端隊列中,進入隊列的頭部。當一個工做線程的隊列裏暫時沒有任務時,它會隨機從其餘工做線程的隊列的尾部獲取一個任務(工做竊取算法)。 
Fork/Join框架的實現原理 
  ForkJoinPool由ForkJoinTask數組和ForkJoinWorkerThread數組組成,ForkJoinTask數組負責將存放程序提交給ForkJoinPool,而ForkJoinWorkerThread負責執行這

20、原子操做類

java.util.concurrent.atomic包下,能夠分爲四種類型的原子更新類:原子更新基本類型、原子更新數組類型、原子更新引用和原子更新屬性。

原子更新基本類型 
使用原子方式更新基本類型,共包括3個類: 
AtomicBoolean:原子更新布爾變量 
AtomicInteger:原子更新整型變量 
AtomicLong:原子更新長整型變量

原子更新數組 
經過原子更新數組裏的某個元素,共有3個類: 
AtomicIntegerArray:原子更新整型數組的某個元素 
AtomicLongArray:原子更新長整型數組的某個元素 
AtomicReferenceArray:原子更新引用類型數組的某個元素 
AtomicIntegerArray經常使用的方法有: 
int addAndSet(int i, int delta):以原子方式將輸入值與數組中索引爲i的元素相加 
boolean compareAndSet(int i, int expect, int update):若是當前值等於預期值,則以原子方式更新數組中索引爲i的值爲update值

原子更新引用類型 
AtomicReference:原子更新引用類型 
AtomicReferenceFieldUpdater:原子更新引用類型裏的字段 
AtomicMarkableReference:原子更新帶有標記位的引用類型。

原子更新字段類 
若是須要原子更新某個類的某個字段,就須要用到原子更新字段類,能夠使用如下幾個類: 
AtomicIntegerFieldUpdater:原子更新整型字段 
AtomicLongFieldUpdater:原子更新長整型字段 
AtomicStampedReference:原子更新帶有版本號的引用類型。 
要想原子更新字段,須要兩個步驟: 
每次必須使用newUpdater建立一個更新器,而且須要設置想要更新的類的字段 
更新類的字段(屬性)必須爲public volatile

2一、同步屏障CyclicBarrier

CyclicBarrier 的字面意思是可循環使用(Cyclic)的屏障(Barrier)。它要作的事情是,讓一組線程到達一個屏障(也能夠叫同步點)時被阻塞,直到最後一個線程到達屏障時,屏障纔會開門,全部被屏障攔截的線程纔會繼續幹活。CyclicBarrier默認的構造方法是CyclicBarrier(int parties),其參數表示屏障攔截的線程數量,每一個線程調用await方法告訴CyclicBarrier我已經到達了屏障,而後當前線程被阻塞。 
CyclicBarrier和CountDownLatch的區別

CountDownLatch的計數器只能使用一次。而CyclicBarrier的計數器能夠使用reset() 方法重置。因此CyclicBarrier能處理更爲複雜的業務場景,好比若是計算髮生錯誤,能夠重置計數器,並讓線程們從新執行一次。 
CyclicBarrier還提供其餘有用的方法,好比getNumberWaiting方法能夠得到CyclicBarrier阻塞的線程數量。isBroken方法用來知道阻塞的線程是否被中斷。好比如下代碼執行完以後會返回true。

175. 2二、Semaphore

Semaphore(信號量)是用來控制同時訪問特定資源的線程數量,它經過協調各個線程,以保證合理的使用公共資源 
Semaphore能夠用於作流量控制,特別公用資源有限的應用場景,好比數據庫鏈接。假若有一個需求,要讀取幾萬個文件的數據,由於都是IO密集型任務,咱們能夠啓動幾十個線程併發的讀取,可是若是讀到內存後,還須要存儲到數據庫中,而數據庫的鏈接數只有10個,這時咱們必須控制只有十個線程同時獲取數據庫鏈接保存數據,不然會報錯沒法獲取數據庫鏈接。這個時候,咱們就能夠使用Semaphore來作流控,代碼以下:

控制併發線程數的Semaphore

176. 2三、死鎖,以及解決死鎖

死鎖產生的四個必要條件

互斥條件:資源是獨佔的且排他使用,進程互斥使用資源,即任意時刻一個資源只能給一個進程使用,其餘進程若申請一個資源,而該資源被另外一進程佔有時,則申請者等待直到資源被佔有者釋放。 
不可剝奪條件:進程所得到的資源在未使用完畢以前,不被其餘進程強行剝奪,而只能由得到該資源的進程資源釋放。 
請求和保持條件:進程每次申請它所須要的一部分資源,在申請新的資源的同時,繼續佔用已分配到的資源。 
循環等待條件:在發生死鎖時必然存在一個進程等待隊列{P1,P2,…,Pn},其中P1等待P2佔有的資源,P2等待P3佔有的資源,…,Pn等待P1佔有的資源,造成一個進程等待環路,環路中每個進程所佔有的資源同時被另外一個申請,也就是前一個進程佔有後一個進程所深情地資源。

解決死鎖

一是死鎖預防,就是不讓上面的四個條件同時成立。 
二是,合理分配資源。 
三是使用銀行家算法,若是該進程請求的資源操做系統剩餘量能夠知足,那麼就分配。

177. 2四、進程間的通訊方式

管道( pipe):管道是一種半雙工的通訊方式,數據只能單向流動,並且只能在具備親緣關係的進程間使用。進程的親緣關係一般是指父子進程關係。

有名管道 (named pipe) : 有名管道也是半雙工的通訊方式,可是它容許無親緣關係進程間的通訊。

信號量( semophore ) : 信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。它常做爲一種鎖機制,防止某進程正在訪問共享資源時,其餘進程也訪問該資源。所以,主要做爲進程間以及同一進程內不一樣線程之間的同步手段。

消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩衝區大小受限等缺點。

信號 ( sinal ) : 信號是一種比較複雜的通訊方式,用於通知接收進程某個事件已經發生。

共享內存( shared memory ) :共享內存就是映射一段能被其餘進程所訪問的內存,這段共享內存由一個進程建立,但多個進程均可以訪問。共享內存是最快的 IPC 方式,它是針對其餘進程間通訊方式運行效率低而專門設計的。它每每與其餘通訊機制,如信號量,配合使用,來實現進程間的同步和通訊。

套接字( socket ) : 套解口也是一種進程間通訊機制,與其餘通訊機制不一樣的是,它可用於不一樣機器間的進程通訊。

中斷

interrupt()的做用是中斷本線程。 
本線程中斷本身是被容許的;其它線程調用本線程的interrupt()方法時,會經過checkAccess()檢查權限。這有可能拋出SecurityException異常。 
若是本線程是處於阻塞狀態:調用線程的wait(), wait(long)或wait(long, int)會讓它進入等待(阻塞)狀態,或者調用線程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也會讓它進入阻塞狀態。若線程在阻塞狀態時,調用了它的interrupt()方法,那麼它的「中斷狀態」會被清除而且會收到一個InterruptedException異常。例如,線程經過wait()進入阻塞狀態,此時經過interrupt()中斷該線程;調用interrupt()會當即將線程的中斷標記設爲「true」,可是因爲線程處於阻塞狀態,因此該「中斷標記」會當即被清除爲「false」,同時,會產生一個InterruptedException的異常。 
若是線程被阻塞在一個Selector選擇器中,那麼經過interrupt()中斷它時;線程的中斷標記會被設置爲true,而且它會當即從選擇操做中返回。 
若是不屬於前面所說的狀況,那麼經過interrupt()中斷線程時,它的中斷標記會被設置爲「true」。 
中斷一個「已終止的線程」不會產生任何操做。

終止處於「阻塞狀態」的線程 
一般,咱們經過「中斷」方式終止處於「阻塞狀態」的線程。 
當線程因爲被調用了sleep(), wait(), join()等方法而進入阻塞狀態;若此時調用線程的interrupt()將線程的中斷標記設爲true。因爲處於阻塞狀態,中斷標記會被清除,同時產生一個InterruptedException異常。將InterruptedException放在適當的爲止就能終止線程, 

終止處於「運行狀態」的線程

interrupted() 和 isInterrupted()的區別

最後談談 interrupted() 和 isInterrupted()。 
interrupted() 和 isInterrupted()都可以用於檢測對象的「中斷標記」。 
區別是,interrupted()除了返回中斷標記以外,它還會清除中斷標記(即將中斷標記設爲false);而isInterrupted()僅僅返回中斷標記。 
interrupt()和線程終止方式

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

178. 一、經常使用設計模式

單例模式:懶漢式、餓漢式、雙重校驗鎖、靜態加載,內部類加載、枚舉類加載。保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

代理模式:動態代理和靜態代理,何時使用動態代理。

適配器模式:將一個類的接口轉換成客戶但願的另一個接口。適配器模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。

裝飾者模式:動態給類加功能。

觀察者模式:有時被稱做發佈/訂閱模式,觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知全部觀察者對象,使它們可以自動更新本身。

策略模式:定義一系列的算法,把它們一個個封裝起來, 而且使它們可相互替換。

外觀模式:爲子系統中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。

命令模式:將一個請求封裝成一個對象,從而使您能夠用不一樣的請求對客戶進行參數化。

建立者模式:將一個複雜的構建與其表示相分離,使得一樣的構建過程能夠建立不一樣的表示。

抽象工廠模式:提供一個建立一系列相關或相互依賴對象的接口,而無需指定它們具體的類。

 

179. 二、基礎知識

Java基本類型哪些,所佔字節和範圍

Set、List、Map的區別和聯繫

何時使用Hashmap

何時使用Linkedhashmap、Concurrenthashmap、Weakhashmap

哪些集合類是線程安全的

爲何Set、List、map不實現Cloneable和Serializable接口

Concurrenthashmap的實現,1.7和1.8的實現

Arrays.sort的實現

何時使用CopyOnArrayList

volatile的使用

synchronied的使用

reentrantlock的實現和Synchronied的區別

CAS的實現原理以及問題

AQS的實現原理

接口和抽象類的區別,何時使用

類加載機制的步驟,每一步作了什麼,static和final修改的成員變量的加載時機

雙親委派模型

反射機制:反射動態擦除泛型、反射動態調用方法等

動態綁定:父類引用指向子類對象

JVM內存管理機制:有哪些區域,每一個區域作了什麼

JVM垃圾回收機制:垃圾回收算法 垃圾回收器 垃圾回收策略

jvm參數的設置和jvm調優

什麼狀況產生年輕代內存溢出、什麼狀況產生年老代內存溢出

內部類:靜態內部類和匿名內部類的使用和區別

Redismemcached:何時選擇redis,何時選擇memcached,內存模型和存儲策略是什麼樣的

MySQL的基本操做 主從數據庫一致性維護

mysql的優化策略有哪些

mysql索引的實現 B+樹的實現原理

什麼狀況索引不會命中,會形成全表掃描

java中bio nio aio的區別和聯繫

爲何bio是阻塞的 nio是非阻塞的 nio是模型是什麼樣的

Java io的總體架構和使用的設計模式

Reactor模型和Proactor模型

http請求報文結構和內容

http三次握手和四次揮手

rpc相關:如何設計一個rpc框架,從io模型 傳輸協議 序列化方式綜合考慮

Linux命令 統計,排序,前幾問題等

StringBuff 和StringBuilder的實現,底層實現是經過byte數據,外加數組的拷貝來實現的

cas操做的使用

內存緩存和數據庫的一致性同步實現

微服務的優缺點

線程池的參數問題

ip問題 如何判斷ip是否在多個ip段中

判斷數組兩個中任意兩個數之和是否爲給定的值

樂觀鎖和悲觀鎖的實現

synchronized實現原理

你在項目中遇到的困難和怎麼解決的

你在項目中完成的比較出色的亮點

消息隊列廣播模式和發佈/訂閱模式的區別

生產者消費者代碼實現

死鎖代碼實現

線程池:參數,每一個參數的做用,幾種不一樣線程池的比較,阻塞隊列的使用,拒絕策略

Future和ListenableFuture 異步回調相關

算法相關:判斷可否從數組中找出兩個數字和爲給定值,隨機生成1~10000不重複並放入數組,求數組的子數組的最大和,二分查找算法的實現及其時間複雜計算

 

180. 三、其它

算法:經常使用排序算法,二分查找,鏈表相關,數組相關,字符串相關,樹相關等

常見序列化協議及其優缺點

memcached內存原理,爲何是基於塊的存儲

搭建一個rpc須要準備什麼

若是線上服務器頻繁地出現full gc ,如何去排查

若是某一時刻線上機器忽然量變得很大,服務扛不住了,怎麼解決

LUR算法的實現

LinkedHashMap實現LRU

定義棧的數據結構,請在該類型中實現一個可以找到棧最小元素的min函數

海量數據處理的解決思路

reactor模型的演變

阻塞、非阻塞、同步、異步區別

Collection的子接口

jvm調優相關

zookeeper相關,節點類型,如何實現服務發現和服務註冊

nginx負載均衡相關,讓你去實現負載均衡,該怎麼實現

linux命令,awk、cat、sort、cut、grep、uniq、wc、top等

壓力測試相關,怎麼分析,單接口壓測和多狀況下的壓測

你以爲你的有點是什麼,你的缺點是什麼

spring mvc的實現原理

netty底層實現,IO模型,ChannelPipeline的實現和原理

緩存的設計和優化

緩存和數據庫一致性同步解決方案

你所在項目的系統架構,談談總體實現

消息隊列的使用場景

ActiveMQ、RabbitMQ、Kafka的區別

 

 

 

 

 

 

 

 

 

 

181. 1、Java基礎

一、String類爲何是final的。

二、HashMap的源碼,實現原理,底層結構。

三、說說你知道的幾個Java集合類:list、set、queue、map實現類咯。。。

四、描述一下ArrayList和LinkedList各自實現和區別

五、Java中的隊列都有哪些,有什麼區別。

六、反射中,Class.forName和classloader的區別

七、Java七、Java8的新特性(baidu問的,好BT)

八、Java數組和鏈表兩種結構的操做效率,在哪些狀況下(從開頭開始,從結尾開始,從中間開始),哪些操做(插入,查找,刪除)的效率高

九、Java內存泄露的問題調查定位:jmap,jstack的使用等等

十、string、stringbuilder、stringbuffer區別

十一、hashtable和hashmap的區別

1三、異常的結構,運行時異常和非運行時異常,各舉個例子

1四、String a= 「abc」 String b = "abc" String c = new String("abc") String d = "ab" + "c" .他們之間用 == 比較的結果

1五、String 類的經常使用方法

1六、Java 的引用類型有哪幾種

1七、抽象類和接口的區別

1八、java的基礎類型和字節大小。

1九、Hashtable,HashMap,ConcurrentHashMap 底層實現原理與線程安全問題(建議熟悉 jdk 源碼,才能從容應答)

20、若是不讓你用Java Jdk提供的工具,你本身實現一個Map,你怎麼作。說了很久,說了HashMap源代碼,若是我作,就會借鑑HashMap的原理,說了一通HashMap實現

2一、 Hash衝突怎麼辦?哪些解決散列衝突的方法?

2二、HashMap衝突很厲害,最差性能,你會怎麼解決?從O(n)提高到log(n)咯,用二叉排序樹的思路說了一通

2三、rehash

2四、hashCode() 與 equals() 生成算法、方法怎麼重寫

182. 2、Java IO

一、講講IO裏面的常見類,字節流、字符流、接口、實現類、方法阻塞。

二、講講NIO。

三、String 編碼UTF-8 和GBK的區別?

四、何時使用字節流、何時使用字符流?

五、遞歸讀取文件夾下的文件,代碼怎麼實現

183. 3、Java Web

一、session和cookie的區別和聯繫,session的生命週期,多個服務部署時session管理。

二、servlet的一些相關問題

三、webservice相關問題

四、jdbc鏈接,forname方式的步驟,怎麼聲明使用一個事務。舉例並具體代碼

五、無框架下配置web.xml的主要配置內容

六、jsp和servlet的區別 

184. 4、JVM

一、Java的內存模型以及GC算法

二、jvm性能調優都作了什麼

三、介紹JVM中7個區域,而後把每一個區域可能形成內存的溢出的狀況說明

四、介紹GC 和GC Root不正常引用。

五、本身從classload 加載方式,加載機制說開去,從程序運行時數據區,講到內存分配,講到String常量池,講到JVM垃圾回收機制,算法,hotspot。反正就是各類擴展

六、jvm 如何分配直接內存, new 對象如何不分配在堆而是棧上,常量池解析

七、數組多大放在 JVM 老年代(不僅是設置 PretenureSizeThreshold ,問一般多大,沒作過一問便知)

八、老年代中數組的訪問方式

九、GC 算法,永久代對象如何 GC , GC 有環怎麼處理

十、誰會被 GC ,何時 GC

十一、若是想不被 GC 怎麼辦

十二、若是想在 GC 中生存 1 次怎麼辦

185. 5、開源框架

一、hibernate和ibatis的區別

二、講講mybatis的鏈接池。

三、spring框架中須要引用哪些jar包,以及這些jar包的用途

4. springMVC的原理

五、springMVC註解的意思

六、spring中beanFactory和ApplicationContext的聯繫和區別

七、spring注入的幾種方式(循環注入)

八、spring如何實現事物管理的

九、springIOC

十、spring AOP的原理

十一、hibernate中的1級和2級緩存的使用方式以及區別原理(Lazy-Load的理解)

十二、Hibernate的原理體系架構,五大核心接口,Hibernate對象的三種狀態轉換,事務管理。

186. 6、多線程

一、Java建立線程以後,直接調用start()方法和run()的區別

二、經常使用的線程池模式以及不一樣線程池的使用場景

三、newFixedThreadPool此種線程池若是線程數達到最大值後會怎麼辦,底層原理。

四、多線程之間通訊的同步問題,synchronized鎖的是對象,衍伸出和synchronized相關不少的具體問題,例如同一個類不一樣方法都有synchronized鎖,一個對象是否能夠同時訪問。或者一個類的static構造方法加上synchronized以後的鎖的影響。

五、瞭解可重入鎖的含義,以及ReentrantLock 和synchronized的區別

六、同步的數據結構,例如concurrentHashMap的源碼理解以及內部實現原理,爲何他是同步的且效率高

七、atomicinteger和volatile等線程安全操做的關鍵字的理解和使用

八、線程間通訊,wait和notify

九、定時線程的使用

十、場景:在一個主線程中,要求有大量(不少不少)子線程執行完以後,主線程才執行完成。多種方式,考慮效率。

十一、進程和線程的區別

十二、什麼叫線程安全?舉例說明

1三、線程的幾種狀態

1四、併發、同步的接口或方法

1五、HashMap 是否線程安全,爲什麼不安全。 ConcurrentHashMap,線程安全,爲什麼安全。底層實現是怎麼樣的。

1六、J.U.C下的常見類的使用。 ThreadPool的深刻考察; BlockingQueue的使用。(take,poll的區別,put,offer的區別);原子類的實現。

1七、簡單介紹下多線程的狀況,從創建一個線程開始。而後怎麼控制同步過程,多線程經常使用的方法和結構

1八、volatile的理解

1九、實現多線程有幾種方式,多線程同步怎麼作,說說幾個線程裏經常使用的方法

187. 7、網絡通訊

一、http是無狀態通訊,http的請求方式有哪些,能夠本身定義新的請求方式麼。

二、socket通訊,以及長鏈接,分包,鏈接異常斷開的處理。

三、socket通訊模型的使用,AIO和NIO。

四、socket框架netty的使用,以及NIO的實現原理,爲何是異步非阻塞。

五、同步和異步,阻塞和非阻塞。

六、OSI七層模型,包括TCP,IP的一些基本知識

七、http中,get post的區別

八、說說http,tcp,udp之間關係和區別。

九、說說瀏覽器訪問www.taobao.com,經歷了怎樣的過程。

十、HTTP協議、  HTTPS協議,SSL協議及完整交互過程;

十一、tcp的擁塞,快回傳,ip的報文丟棄

十二、https處理的一個過程,對稱加密和非對稱加密

1三、head各個特色和區別

1四、說說瀏覽器訪問www.taobao.com,經歷了怎樣的過程。

188. 8、數據庫MySql

一、MySql的存儲引擎的不一樣

二、單個索引、聯合索引、主鍵索引

三、Mysql怎麼分表,以及分表後若是想按條件分頁查詢怎麼辦(若是不是按分表字段來查詢的話,幾乎效率低下,無解)

四、分表以後想讓一個id多個表是自增的,效率實現

五、MySql的主從實時備份同步的配置,以及原理(從庫讀主庫的binlog),讀寫分離

六、寫SQL語句。。。

七、索引的數據結構,B+樹

八、事務的四個特性,以及各自的特色(原子、隔離)等等,項目怎麼解決這些問題

九、數據庫的鎖:行鎖,表鎖;樂觀鎖,悲觀鎖

十、數據庫事務的幾種粒度;

十一、關係型和非關係型數據庫區別

189. 9、設計模式 

一、單例模式:飽漢、餓漢。以及餓漢中的延遲加載,雙重檢查

二、工廠模式、裝飾者模式、觀察者模式。

三、工廠方法模式的優勢(低耦合、高內聚,開放封閉原則) 

190. 10、算法 

一、使用隨機算法產生一個數,要求把1-1000W之間這些數所有生成。(考察高效率,解決產生衝突的問題)

二、兩個有序數組的合併排序

三、一個數組的倒序

四、計算一個正整數的正平方根

五、說白了就是常見的那些查找、排序算法以及各自的時間複雜度

六、二叉樹的遍歷算法

七、DFS,BFS算法

九、比較重要的數據結構,如鏈表,隊列,棧的基本理解及大體實現。

十、排序算法與時空複雜度(快排爲何不穩定,爲何你的項目還在用)

十一、逆波蘭計算器

十二、Hoffman 編碼

1三、查找樹與紅黑樹 

191. 11、併發與性能調優 

一、有個每秒鐘5k個請求,查詢手機號所屬地的筆試題(記得不完整,沒列出),如何設計算法?請求再多,好比5w,如何設計整個系統?

二、高併發狀況下,咱們系統是如何支撐大量的請求的

三、集羣如何同步會話狀態

四、負載均衡的原理

五、若是有一個特別大的訪問量,到數據庫上,怎麼作優化(DB設計,DBIO,SQL優化,Java優化)

六、若是出現大面積併發,在不增長服務器的基礎上,如何解決服務器響應不及時問題「。

七、假如你的項目出現性能瓶頸了,你以爲可能會是哪些方面,怎麼解決問題。

八、如何查找 形成 性能瓶頸出現的位置,是哪一個位置照成性能瓶頸。

九、你的項目中使用過緩存機制嗎?有沒用用戶非本地緩存 

192. 12、其餘 

一、 經常使用的linux下的命令

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SPRING

193. 一、什麼是Spring框架?Spring框架有哪些主要模塊?

Spring框架是一個爲Java應用程序的開發提供了綜合、普遍的基礎性支持的Java平臺。

Spring幫助開發者解決了開發中基礎性的問題,使得開發人員能夠專一於應用程序的開發。

Spring框架自己亦是按照設計模式精心打造,這使得咱們能夠在開發環境中安心的集成Spring框架,沒必要擔憂Spring是如何在後臺進行工做的。

Spring框架至今已集成了20多個模塊。這些模塊主要被分以下圖所示的核心容器、數據訪問/集成,、Web、AOP(面向切面編程)、工具、消息和測試模塊。

 

194. 二、使用Spring框架能帶來哪些好處?

下面列舉了一些使用Spring框架帶來的主要好處:

  • Dependency Injection(DI) 方法使得構造器和JavaBean properties文件中的依賴關係一目瞭然。
  • EJB容器相比較,IoC容器更加趨向於輕量級。這樣一來IoC容器在有限的內存和CPU資源的狀況下進行應用程序的開發和發佈就變得十分有利。
  • Spring並無閉門造車,Spring利用了已有的技術好比ORM框架、logging框架、J2EE、Quartz和JDK Timer,以及其餘視圖技術。
  • Spring框架是按照模塊的形式來組織的。由包和類的編號就能夠看出其所屬的模塊,開發者僅僅須要選用他們須要的模塊便可。
  • 測試一項用Spring開發的應用程序十分簡單,由於測試相關的環境代碼都已經囊括在框架中了。更加簡單的是,利用JavaBean形式的POJO類,能夠很方便的利用依賴注入來寫入測試數據。
  • Spring的Web框架亦是一個精心設計的Web MVC框架,爲開發者們在web框架的選擇上提供了一個除了主流框架好比Struts、過分設計的、不流行web框架的之外的有力選項。
  • Spring提供了一個便捷的事務管理接口,適用於小型的本地事物處理(好比在單DB的環境下)和複雜的共同事物處理(好比利用JTA的複雜DB環境)。

195. 三、什麼是控制反轉(IOC)?什麼是依賴注入?

控制反轉是應用於軟件工程領域中的,在運行時被裝配器對象來綁定耦合對象的一種編程技巧,對象之間耦合關係在編譯時一般是未知的。在傳統的編程方式中,業務邏輯的流程是由應用程序中的早已被設定好關聯關係的對象來決定的。在使用控制反轉的狀況下,業務邏輯的流程是由對象關係圖來決定的,該對象關係圖由裝配器負責實例化,這種實現方式還能夠將對象之間的關聯關係的定義抽象化。而綁定的過程是經過「依賴注入」實現的。

控制反轉是一種以給予應用程序中目標組件更多控制爲目的設計範式,並在咱們的實際工做中起到了有效的做用。

依賴注入是在編譯階段還沒有知所需的功能是來自哪一個的類的狀況下,將其餘對象所依賴的功能對象實例化的模式。這就須要一種機制用來激活相應的組件以提供特定的功能,因此依賴注入是控制反轉的基礎。不然若是在組件不受框架控制的狀況下,框架又怎麼知道要建立哪一個組件?

Java中依然注入有如下三種實現方式:

  1. 構造器注入
  2. Setter方法注入
  3. 接口注入

196. 四、請解釋下Spring框架中的IoC?

Spring中的 org.springframework.beans 包和 org.springframework.context包構成了Spring框架IoC容器的基礎。

BeanFactory 接口提供了一個先進的配置機制,使得任何類型的對象的配置成爲可能。ApplicationContex接口對BeanFactory(是一個子接口)進行了擴展,在BeanFactory的基礎上添加了其餘功能,好比與Spring的AOP更容易集成,也提供了處理message resource的機制(用於國際化)、事件傳播以及應用層的特別配置,好比針對Web應用的WebApplicationContext。

org.springframework.beans.factory.BeanFactory 是Spring IoC容器的具體實現,用來包裝和管理前面提到的各類bean。BeanFactory接口是Spring IoC 容器的核心接口。

IOC:把對象的建立、初始化、銷燬交給spring來管理,而不是由開發者控制,實現控制反轉。

 

197. 五、BeanFactory和ApplicationContext有什麼區別?

BeanFactory 能夠理解爲含有bean集合的工廠類。BeanFactory 包含了種bean的定義,以便在接收到客戶端請求時將對應的bean實例化。

BeanFactory還能在實例化對象的時生成協做類之間的關係。此舉將bean自身與bean客戶端的配置中解放出來。BeanFactory還包含了bean生命週期的控制,調用客戶端的初始化方法(initialization methods)和銷燬方法(destruction methods)。

從表面上看,application context如同bean factory同樣具備bean定義、bean關聯關係的設置,根據請求分發bean的功能。但applicationcontext在此基礎上還提供了其餘的功能。

  1. 提供了支持國際化的文本消息
  2. 統一的資源文件讀取方式
  3. 已在監聽器中註冊的bean的事件

如下是三種較常見的 ApplicationContext 實現方式:

一、ClassPathXmlApplicationContext:從classpath的XML配置文件中讀取上下文,並生成上下文定義。應用程序上下文從程序環境變量中取得。

[html] view plain copy

  1. ApplicationContext context = new ClassPathXmlApplicationContext(「bean.xml」);    

二、FileSystemXmlApplicationContext :由文件系統中的XML配置文件讀取上下文。

[html] view plain copy

  1. ApplicationContext context = new FileSystemXmlApplicationContext(「bean.xml」);   

三、XmlWebApplicationContext:由Web應用的XML文件讀取上下文。

 

198. 六、Spring有幾種配置方式?

Spring配置到應用開發中有如下三種方式:

  1. 基於XML的配置
  2. 基於註解的配置
  3. 基於Java的配置

199. 七、如何用基於XML配置的方式配置Spring?

Spring框架中,依賴和服務須要在專門的配置文件來實現,我經常使用的XML格式的配置文件。這些配置文件的格式一般用<beans>開頭,而後一系列的bean定義和專門的應用配置選項組成。

SpringXML配置的主要目的時候是使全部的Spring組件均可以用xml文件的形式來進行配置。這意味着不會出現其餘的Spring配置類型(好比聲明的方式或基於Java Class的配置方式)

Spring的XML配置方式是使用被Spring命名空間的所支持的一系列的XML標籤來實現的。Spring有如下主要的命名空間:context、beans、jdbc、tx、aop、mvc和aso。

如:

[html] view plain copy

  1. <beans>    
  2. <!-- JSON Support -->    
  3. <bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>    
  4. <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>    
  5. <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/>    
  6. </beans>   

下面這個web.xml僅僅配置了DispatcherServlet,這件最簡單的配置便能知足應用程序配置運行時組件的需求。

 

200. 八、如何用基於Java配置的方式配置Spring?

Spring對Java配置的支持是由@Configuration註解和@Bean註解來實現的。由@Bean註解的方法將會實例化、配置和初始化一個新對象,這個對象將由Spring的IoC容器來管理。@Bean聲明所起到的做用與<bean/> 元素相似。被@Configuration所註解的類則表示這個類的主要目的是做爲bean定義的資源。被@Configuration聲明的類能夠經過在同一個類的內部調用@bean方法來設置嵌入bean的依賴關係。

最簡單的@Configuration 聲明類請參考下面的代碼:

[java] view plain copy

  1. @Configuration    
  2. public class AppConfig{    
  3. @Bean    
  4. public MyService myService() {    
  5. return new MyServiceImpl();    
  6. }    
  7. }   

對於上面的@Beans配置文件相同的XML配置文件以下:

[html] view plain copy

  1. <beans>    
  2. <bean id="myService" class="com.somnus.services.MyServiceImpl"/>    
  3. </beans>   

上述配置方式的實例化方式以下:利用AnnotationConfigApplicationContext 類進行實例化

 

要使用組件組建掃描,僅需用@Configuration進行註解便可:

[java] view plain copy

  1. @Configuration    
  2. @ComponentScan(basePackages = "com.somnus")    
  3. public class AppConfig  {    
  4. ...    
  5. }   

在上面的例子中,com.acme包首先會被掃到,而後再容器內查找被@Component 聲明的類,找到後將這些類按照Sring bean定義進行註冊。

若是你要在你的web應用開發中選用上述的配置的方式的話,須要用AnnotationConfigWebApplicationContext 類來讀取配置文件,能夠用來配置Spring的Servlet監聽器ContextLoaderListener或者Spring MVC的DispatcherServlet。

201. 九、怎樣用註解的方式配置Spring?

Spring在2.5版本之後開始支持用註解的方式來配置依賴注入。能夠用註解的方式來替代XML方式的bean描述,能夠將bean描述轉移到組件類的內部,只須要在相關類上、方法上或者字段聲明上使用註解便可。註解注入將會被容器在XML注入以前被處理,因此後者會覆蓋掉前者對於同一個屬性的處理結果。

註解裝配在Spring中是默認關閉的。因此須要在Spring文件中配置一下才能使用基於註解的裝配模式。若是你想要在你的應用程序中使用關於註解的方法的話,請參考以下的配置。

[html] view plain copy

  1. <beans>    
  2. <context:annotation-config/>    
  3. <!-- bean definitions go here -->    
  4. </beans>    

 <context:annotation-config/>標籤配置完成之後,就能夠用註解的方式在Spring中向屬性、方法和構造方法中自動裝配變量。

下面是幾種比較重要的註解類型:

  1. @Required:該註解應用於設值方法。
  2. @Autowired:該註解應用於有值設值方法、非設值方法、構造方法和變量。
  3. @Qualifier:該註解和@Autowired註解搭配使用,用於消除特定bean自動裝配的歧義。
  4. JSR-250 Annotations:Spring支持基於JSR-250 註解的如下註解,@Resource、@PostConstruct 和 @PreDestroy。

202. 十、請解釋Spring Bean的生命週期?

Spring Bean的生命週期簡單易懂。在一個bean實例被初始化時,須要執行一系列的初始化操做以達到可用的狀態。一樣的,當一個bean不在被調用時須要進行相關的析構操做,並從bean容器中移除。

Spring bean factory 負責管理在spring容器中被建立的bean的生命週期。Bean的生命週期由兩組回調(call back)方法組成。

  1. 初始化以後調用的回調方法。
  2. 銷燬以前調用的回調方法。

Spring框架提供瞭如下四種方式來管理bean的生命週期事件:

  • InitializingBean和DisposableBean回調接口
  • 針對特殊行爲的其餘Aware接口
  • Bean配置文件中的Custom init()方法和destroy()方法
  • @PostConstruct和@PreDestroy註解方式

使用customInit() customDestroy()方法管理bean生命週期的代碼樣例以下:

[html] view plain copy

  1. <beans>    
  2. <bean id="demoBean" class="com.somnus.task.DemoBean" init-method="customInit" destroy-method="customDestroy"></bean>    
  3. </beans>    

203. 十一、Spring Bean的做用域之間有什麼區別?

Spring容器中的bean能夠分爲5個範圍。全部範圍的名稱都是自說明的,可是爲了不混淆,仍是讓咱們來解釋一下:

  1. singleton:這種bean範圍是默認的,這種範圍確保無論接受到多少個請求,每一個容器中只有一個bean的實例,單例的模式由bean factory自身來維護。
  2. prototype:原形範圍與單例範圍相反,爲每個bean請求提供一個實例。
  3. request:在請求bean範圍內會每個來自客戶端的網絡請求建立一個實例,在請求完成之後,bean會失效並被垃圾回收器回收。
  4. Session:與請求範圍相似,確保每一個session中有一個bean的實例,在session過時後,bean會隨之失效。
  5. global-session:global-session和Portlet應用相關。當你的應用部署在Portlet容器中工做時,它包含不少portlet。若是你想要聲明讓全部的portlet共用全局的存儲變量的話,那麼這全局變量須要存儲在global-session中。

全局做用域與Servlet中的session做用域效果相同。

204. 十二、什麼是Spring inner beans?

Spring框架中,不管什麼時候bean被使用時,當僅被調用了一個屬性。一個明智的作法是將這個bean聲明爲內部bean。內部bean能夠用setter注入「屬性」和構造方法注入「構造參數」的方式來實現。

好比,在咱們的應用程序中,一個Customer類引用了一個Person類,咱們的要作的是建立一個Person的實例,而後在Customer內部使用。

內部bean的聲明方式以下:

 

205. 1三、Spring框架中的單例Beans是線程安全的麼?

Spring框架並無對單例bean進行任何多線程的封裝處理。關於單例bean的線程安全和併發問題須要開發者自行去搞定。但實際上,大部分的Spring bean並無可變的狀態(好比Serview類和DAO類),因此在某種程度上說Spring的單例bean是線程安全的。若是你的bean有多種狀態的話(好比 View Model 對象),就須要自行保證線程安全。
最淺顯的解決辦法就是將多態bean的做用域由「singleton」變動爲「prototype」。

206. 1四、請舉例說明如何在Spring中注入一個Java Collection?

Spring提供瞭如下四種集合類的配置元素:

  • <list> :   該標籤用來裝配可重複的list值。
  • <set> :    該標籤用來裝配沒有重複的set值。
  • <map>:   該標籤可用來注入鍵和值能夠爲任何類型的鍵值對。
  • <props> : 該標籤支持注入鍵和值都是字符串類型的鍵值對。

下面看一下具體的例子:

 

207. 1五、如何向Spring Bean中注入一個Java.util.Properties?

第一種方法是使用以下面代碼所示的<props> 標籤:

也可用」util:」命名空間來從properties文件中建立出一個propertiesbean,而後利用setter方法注入bean的引用。

208. 1六、請解釋Spring Bean的自動裝配?

Spring框架中,在配置文件中設定bean的依賴關係是一個很好的機制,Spring容器還能夠自動裝配合做關係bean之間的關聯關係。這意味着Spring能夠經過向Bean Factory中注入的方式自動搞定bean之間的依賴關係。自動裝配能夠設置在每一個bean上,也能夠設定在特定的bean上。

下面的XML配置文件代表瞭如何根據名稱將一個bean設置爲自動裝配:

[html] view plain copy

  1. <bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />   

除了bean配置文件中提供的自動裝配模式,還能夠使用@Autowired註解來自動裝配指定的bean。在使用@Autowired註解以前須要在按照以下的配置方式在Spring配置文件進行配置才能夠使用。

[html] view plain copy

  1. <context:annotation-config />  

也能夠經過在配置文件中配置AutowiredAnnotationBeanPostProcessor 達到相同的效果。

[html] view plain copy

  1. <bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>    

配置好之後就能夠使用@Autowired來標註了。

 

209. 1七、請解釋自動裝配模式的區別?

Spring框架中共有5種自動裝配,讓咱們逐一分析。

  1. no:這是Spring框架的默認設置,在該設置下自動裝配是關閉的,開發者須要自行在bean定義中用標籤明確的設置依賴關係。
  2. byName:該選項能夠根據bean名稱設置依賴關係。當向一個bean中自動裝配一個屬性時,容器將根據bean的名稱自動在在配置文件中查詢一個匹配的bean。若是找到的話,就裝配這個屬性,若是沒找到的話就報錯。
  3. byType:該選項能夠根據bean類型設置依賴關係。當向一個bean中自動裝配一個屬性時,容器將根據bean的類型自動在在配置文件中查詢一個匹配的bean。若是找到的話,就裝配這個屬性,若是沒找到的話就報錯。
  4. constructor:造器的自動裝配和byType模式相似,可是僅僅適用於與有構造器相同參數的bean,若是在容器中沒有找到與構造器參數類型一致的bean,那麼將會拋出異常。
  5. autodetect:該模式自動探測使用構造器自動裝配或者byType自動裝配。首先,首先會嘗試找合適的帶參數的構造器,若是找到的話就是用構造器自動裝配,若是在bean內部沒有找到相應的構造器或者是無參構造器,容器就會自動選擇byTpe的自動裝配方式。

210. 1八、如何開啓基於註解的自動裝配?

要使用 @Autowired,須要註冊 AutowiredAnnotationBeanPostProcessor,能夠有如下兩種方式來實現:

一、引入配置文件中的<bean>下引入 <context:annotation-config>

 

211. 1九、請舉例解釋@Required註解?

在產品級別的應用中,IoC容器可能聲明瞭數十萬了bean,bean與bean之間有着複雜的依賴關係。設值註解方法的短板之一就是驗證全部的屬性是否被註解是一項十分困難的操做。能夠經過在<bean>中設置「dependency-check」來解決這個問題。

在應用程序的生命週期中,你可能不大願意花時間在驗證全部bean的屬性是否按照上下文文件正確配置。或者你寧肯驗證某個bean的特定屬性是否被正確的設置。即便是用「dependency-check」屬性也不能很好的解決這個問題,在這種狀況下,你須要使用@Required 註解。

須要用以下的方式使用來標明bean的設值方法。

RequiredAnnotationBeanPostProcessorSpring中的後置處理用來驗證被@Required 註解的bean屬性是否被正確的設置了。在使用RequiredAnnotationBeanPostProcesso來驗證bean屬性以前,首先要在IoC容器中對其進行註冊:

[html] view plain copy

  1. <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />    

可是若是沒有屬性被用 @Required 註解過的話,後置處理器會拋出一個BeanInitializationException 異常。

212. 20、請舉例解釋@Autowired註解?

@Autowired註解對自動裝配什麼時候何處被實現提供了更多細粒度的控制。@Autowired註解能夠像@Required註解、構造器同樣被用於在bean的設值方法上自動裝配bean的屬性,一個參數或者帶有任意名稱或帶有多個參數的方法。

好比,能夠在設值方法上使用@Autowired註解來替代配置文件中的 <property>元素。當Spring容器在setter方法上找到@Autowired註解時,會嘗試用byType 自動裝配。

固然咱們也能夠在構造方法上使用@Autowired 註解。帶有@Autowired 註解的構造方法意味着在建立一個bean時將會被自動裝配,即使在配置文件中使用<constructor-arg> 元素。

 

213. 2一、請舉例說明@Qualifier註解?

@Qualifier註解意味着能夠在被標註bean的字段上能夠自動裝配。Qualifier註解能夠用來取消Spring不能取消的bean應用。

下面的示例將會在Customer的person屬性中自動裝配person的值。

[java] view plain copy

  1. public class Customer{    
  2. @Autowired    
  3. private Person person;    
  4. }   

下面咱們要在配置文件中來配置Person類。

Spring會知道要自動裝配哪一個person bean麼?不會的,可是運行上面的示例時,會拋出下面的異常:

[html] view plain copy

  1. Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:    
  2. No unique bean of type [com.howtodoinjava.common.Person] is defined:    
  3. expected single matching bean but found 2: [personA, personB]    

要解決上面的問題,須要使用 @Quanlifier註解來告訴Spring容器要裝配哪一個bean:

[java] view plain copy

  1. public class Customer{    
  2. @Autowired    
  3. @Qualifier("personA")    
  4. private Person person;    
  5. }  

 

214. 2二、構造方法注入和設值注入有什麼區別?

請注意如下明顯的區別:

  1. 在設值注入方法支持大部分的依賴注入,若是咱們僅須要注入int、string和long型的變量,咱們不要用設值的方法注入。對於基本類型,若是咱們沒有注入的話,能夠爲基本類型設置默認值。在構造方法注入不支持大部分的依賴注入,由於在調用構造方法中必須傳入正確的構造參數,不然的話爲報錯。
  2. 設值注入不會重寫構造方法的值。若是咱們對同一個變量同時使用了構造方法注入又使用了設置方法注入的話,那麼構造方法將不能覆蓋由設值方法注入的值。很明顯,由於構造方法盡在對象被建立時調用。
  3. 在使用設值注入時有可能還不能保證某種依賴是否已經被注入,也就是說這時對象的依賴關係有多是不完整的。而在另外一種狀況下,構造器注入則不容許生成依賴關係不完整的對象。
  4. 在設值注入時若是對象A和對象B互相依賴,在建立對象A時Spring會拋出sObjectCurrentlyInCreationException異常,由於在B對象被建立以前A對象是不能被建立的,反之亦然。因此Spring用設值注入的方法解決了循環依賴的問題,因對象的設值方法是在對象被建立以前被調用的。

215. 2三、Spring框架中有哪些不一樣類型的事件?

Spring的ApplicationContext 提供了支持事件和代碼中監聽器的功能。

咱們能夠建立bean用來監聽在ApplicationContext 中發佈的事件。ApplicationEvent類和在ApplicationContext接口中處理的事件,若是一個bean實現了ApplicationListener接口,當一個ApplicationEvent 被髮布之後,bean會自動被通知。

 

Spring 提供瞭如下5中標準的事件:

  1. 上下文更新事件(ContextRefreshedEvent):該事件會在ApplicationContext被初始化或者更新時發佈。也能夠在調用ConfigurableApplicationContext 接口中的refresh()方法時被觸發。
  2. 上下文開始事件(ContextStartedEvent):當容器調用ConfigurableApplicationContext的Start()方法開始/從新開始容器時觸發該事件。
  3. 上下文中止事件(ContextStoppedEvent):當容器調用ConfigurableApplicationContext的Stop()方法中止容器時觸發該事件。
  4. 上下文關閉事件(ContextClosedEvent):當ApplicationContext被關閉時觸發該事件。容器被關閉時,其管理的全部單例Bean都被銷燬。
  5. 請求處理事件(RequestHandledEvent):在Web應用中,當一個http請求(request)結束觸發該事件。

除了上面介紹的事件之外,還能夠經過擴展ApplicationEvent 類來開發自定義的事件。

爲了監聽這個事件,還須要建立一個監聽器:


以後經過applicationContext接口的publishEvent()方法來發布自定義事件。

[java] view plain copy

  1. CustomApplicationEvent customEvent = new CustomApplicationEvent(applicationContext, "Test message");    
  2. applicationContext.publishEvent(customEvent);    

 

216. 2四、FileSystemResource和ClassPathResource有何區別?

在FileSystemResource 中須要給出spring-config.xml文件在你項目中的相對路徑或者絕對路徑。在ClassPathResourcespring會在ClassPath中自動搜尋配置文件,因此要把ClassPathResource 文件放在ClassPath下。

若是將spring-config.xml保存在了src文件夾下的話,只需給出配置文件的名稱便可,由於src文件夾是默認。

簡而言之,ClassPathResource在環境變量中讀取配置文件,FileSystemResource在配置文件中讀取配置文件。

217. 2五、Spring 框架中都用到了哪些設計模式?

Spring框架中使用到了大量的設計模式,下面列舉了比較有表明性的:

  • 代理模式—在AOP和remoting中被用的比較多。
  • 單例模式—在spring配置文件中定義的bean默認爲單例模式。
  • 模板方法—用來解決代碼重複的問題。好比. RestTemplate, JmsTemplate, JpaTemplate。
  • 前端控制器—Spring提供了DispatcherServlet來對請求進行分發。
  • 視圖幫助(View Helper )—Spring提供了一系列的JSP標籤,高效宏來輔助將分散的代碼整合在視圖裏。
  • 依賴注入—貫穿於BeanFactory / ApplicationContext接口的核心理念。
  • 工廠模式—BeanFactory用來建立對象的實例。

轉至:http://blog.csdn.net/lovesomnus/article/details/46470255

相關文章
相關標籤/搜索