2015.03.09--------文章發佈html
2015.03.11--------添加了Java IO機制中的種類和應用場景的解釋,添加了Java內存模型的相關知識點java
2015.03.13--------文章按技術劃分,增長J2EE規範的解釋mysql
2015.04.25--------增長對LRU緩存設計的描述nginx
2015.04.26--------增長對比較流行的開源技術和開源框架的介紹,對於這些技術的理解或使用能夠增長本身的競爭優點,同時擴展本身的眼界web
2015.04.27--------增長對數據庫事務的描述redis
1.接口和抽象類的區別算法
①抽象類裏能夠有構造方法,而接口內不能有構造方法。spring
②抽象類中能夠有普通成員變量,而接口中不能有普通成員變量。sql
③抽象類中能夠包含非抽象的普通方法,而接口中全部的方法必須是抽象的,不能有非抽象的普通方法。mongodb
④抽象類中的抽象方法的訪問類型能夠是public ,protected和默認類型,但接口中的抽象方法只有public和默認類型。
⑤ 抽象類中能夠包含靜態方法,接口內不能包含靜態方法。
⑥抽象類和接口中均可以包含靜態成員變量,抽象類中的靜態成員變量的訪問類型能夠任意,但接口中定義的變量只能是public static類型,而且默認爲public static類型。
⑦一個類能夠實現多個接口,但只能繼承一個抽象類。
⑧接口更多的是在系統框架設計方法發揮做用,主要定義模塊之間的通訊,而抽象類在代碼實現方面發揮做用,能夠實現代碼的重用。
2.Java虛擬機的運行時數據區有幾塊?線程私有和線程共享區域有哪些?
①程序計數器:線程私有,當前縣城執行的字節碼的行號指示器。
②虛擬機棧:線程私有,存放基本數據類型、對象引用和returnAddress類型。
③本地方法棧:爲虛擬機使用到的Native方法服務。
④Java堆:線程共享,存放對象的實例,也是GC回收器管理的主要區域。
⑤方法區:線程共享,存放已被虛擬機加載的類信息、常量、靜態變量、即時編譯後的代碼等數據。
⑥運行時常量池:方法區的一部分,存放編譯期生成的各類字面量和符號引用。
⑦直接內存:不是虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的內存區域,容易引發OOM異常,NIO會調用,不受Java堆大小的限制。
3.HashMap和HashTable區別?
①Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map接口的一個實現。
②Hashtable的方法是同步的,而HashMap的方法不是,所以HashTable是線程安全的,可是代碼的執行效率上要慢於HashMap。
③HashMap容許空值和空鍵,可是HashTable不能夠。
④HashMap非同步實現Map接口,是一個「鏈表數組」的數據結構,最大承載量是16,能夠自動變長,由Entry[]控制(key,value,next),hashCode()判斷key是否重複。
⑤建議須要作同步,使用ConcurrentHashMap,下降了鎖的粒度。在hashMap的基礎上,ConcurrentHashMap將數據分爲多個segment,默認16個(concurrency level),而後每次操做對一個segment加鎖,避免多線程鎖得概率,提升併發效率。這裏在併發讀取時,除了key對應的value爲null以外,並無使用鎖。
4.ArrayList和LinkedList區別?
ArrayList基於數組實現,LinkedList基於鏈表實現,ArrayList增長和刪除比LinkedList慢,可是LinkedList在查找的時須要遞歸查找,效率比ArrayList慢。關於多線程方面,若是要求線程安全的,有一個Vector,不過比較多的使用的是CopyOnWriteArrayList替代ArrayList,CopyOnWriteArrayList適合使用在讀操做遠遠大於寫操做的場景裏,好比緩存。發生修改時候作copy,新老版本分離,保證讀的高性能,適用於以讀爲主的狀況。
5.Set接口
①HashSet是Set接口的典型實現,HashSet按hash算法來存儲元素,所以具備很好的存取和查找性能。特色:不能保證元素的排列順序,順序有可能發生變化;HashSet是異步的;集合元素值能夠是null;當向HashSet集合中存入一個元素時,HashSet會調用該對象的hashCode()方法來獲得該對象的hashCode值,而後根據該HashCode值來肯定該對象在HashSet中存儲的位置。HashSet還有一個子類LinkedHashSet,其集合也是根據元素hashCode值來決定元素的存儲位置,但它同時用鏈表來維護元素的次序,這樣使得元素看起來是以插入的順序保存的,也就是說,當遍歷LinkedHashSet集合元素時,它將會按元素的添加順序來訪問集合裏的元素。因此LinkedHashSet的性能略低於HashSet,但在迭代訪問所有元素時將有很好的性能,由於它以鏈表來維護內部順序。
②TreeSet是SortSet接口的惟一實現,TreeSet能夠確保集合元素處於排序狀態。TreeSet不是根據元素插入順序進行排序的,而是根據元素的值來排序的。TreeSet支持兩種排序方法:天然排序和定製排序。
③EnumSet中全部值都必須是指定枚舉類型的值,它的元素也是有序的,以枚舉值在枚舉類的定義順序來決定集合元素的順序。EnumSet集合不容許加入null元素,不然會拋出NullPointerException異常。EnumSet類沒有暴露任何構造器來建立該類的實例,程序應該經過它提供的static方法來建立EnumSet對象。
④總結:A、HashSet的性能比Treeset好,由於TreeSet須要額外的紅黑樹算法來維護集合元素的次序,只有當須要一個保持排序的Set時,纔會用TreeSet。B、EnumSet是性能最好的,但它只能保存枚舉值。
C、它們都是線程不安全的。
注:Set是一種不包含重複的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
關於HashSet,條目數和容量之和來說,迭代是線性的。所以,若是迭代性能很重要,那就應該慎重選擇一個適當的初始容量。容量選得太大,既浪費空間,也浪費時間。默認的初試容量是101,通常來說,它比你所須要的要多。能夠使用int構造函數來指定初始容量。要分配HashSet的初始容量爲17:
Set s=new HashSet(17);
HashSet另有一個稱做裝載因數(load factor)的"調整參數(tuning parameter)"。
區別: 1. HashSet是經過HashMap實現的,TreeSet是經過TreeMap實現的,只不過Set用的只是Map的key。 2. Map的key和Set都有一個共同的特性就是集合的惟一性.TreeMap更是多了一個排序的功能. 3. hashCode和equal()是HashMap用的, 由於無需排序因此只須要關注定位和惟一性便可. a. hashCode是用來計算hash值的,hash值是用來肯定hash表索引的. b. hash表中的一個索引處存放的是一張鏈表, 因此還要經過equal方法循環比較鏈上的每個對象 才能夠真正定位到鍵值對應的Entry. c. put時,若是hash表中沒定位到,就在鏈表前加一個Entry,若是定位到了,則更換Entry中的value,並返回舊value 4. 因爲TreeMap須要排序,因此須要一個Comparator爲鍵值進行大小比較.固然也是用Comparator定位的. a. Comparator能夠在建立TreeMap時指定 b. 若是建立時沒有肯定,那麼就會使用key.compareTo()方法,這就要求key必須實現Comparable接口. TreeMap是使用Tree數據結構實現的,因此使用compare接口就能夠完成定位了. |
6.Java中Collection和Collections的區別
①java.util.Collection 是一個集合接口,它提供了對集合對象進行基本操做的通用接口方法。java.util.Collections 是一個包裝類。
②它包含有各類有關集合操做的靜態多態方法。此類不能實例化,就像一個工具類,服務於Java的Collection框架。
7.Java容器
JAVA的容器---List,Map,Set
Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap
!其中的Vector和Stack類如今已經極少使用。
8.Cookie Session區別
具體來講cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在服務器端保持狀態的方案.同時咱們也看到,因爲採用服務器端保持狀態的方案在客戶端也須要保存一個標識,因此session機制可能須要藉助於cookie機制來達到保存標識的目的,但實際上它還有其餘選擇.
cookie機制.正統的cookie分發是經過擴展HTTP協議來實現的,服務器經過在HTTP的響應頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie.然而純粹的客戶端腳本如JavaScript或者VBScript也能夠生成cookie.而cookie的使用是由瀏覽器按照必定的原則在後臺自動發送給服務器的.瀏覽器檢查全部存儲的cookie,若是某個cookie所聲明的做用範圍大於等於將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上發送給服務器.
cookie的內容主要包括:名字,值,過時時間,路徑和域.路徑與域一塊兒構成cookie的做用範圍.若不設置過時時間,則表示這個cookie的生命期爲瀏覽器會話期間,關閉瀏覽器窗口,cookie就消失.這種生命期爲瀏覽器會話期的cookie被稱爲會話cookie.會話cookie通常不存儲在硬盤上而是保存在內存裏,固然這種行爲並非規範規定的.若設置了過時時間,瀏覽器就會把cookie保存到硬盤上,關閉後再次打開瀏覽器,這些cookie仍然有效直到超過設定的過時時間.存儲在硬盤上的cookie能夠在不一樣的瀏覽器進程間共享,好比兩個IE窗口.而對於保存在內存裏的cookie,不一樣的瀏覽器有不一樣的處理方式
session機制.session機制是一種服務器端的機制,服務器使用一種相似於散列表的結構(也可能就是使用散列表)來保存信息.
當程序須要爲某個客戶端的請求建立一個session時,服務器首先檢查這個客戶端的請求裏是否已包含了一個session標識(稱爲session id),若是已包含則說明之前已經爲此客戶端建立過session,服務器就按照session id把這個session檢索出來使用(檢索不到,會新建一個),若是客戶端請求不包含sessionid,則爲此客戶端建立一個session而且生成一個與此session相關聯的session id,session id的值應該是一個既不會重複,又不容易被找到規律以仿造的字符串,這個session id將被在本次響應中返回給客戶端保存.
保存這個sessionid的方式能夠採用cookie,這樣在交互過程當中瀏覽器能夠自動的按照規則把這個標識發揮給服務器.通常這個cookie的名字都是相似於SEEESIONID.但cookie能夠被人爲的禁止,則必須有其餘機制以便在cookie被禁止時仍然可以把session id傳遞迴服務器.
常常被使用的一種技術叫作URL重寫,就是把session id直接附加在URL路徑的後面.還有一種技術叫作表單隱藏字段.就是服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時可以把session id傳遞迴服務器.好比:實際上這種技術能夠簡單的用對action應用URL重寫來代替.
九、面向對象和麪向過程的區別:
面向過程就是分析出解決問題所須要的步驟,而後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就能夠了。
面向對象是把構成問題事務分解成各個對象,創建對象的目的不是爲了完成一個步驟,而是爲了描敘某個事物在整個解決問題的步驟中的行爲。
十、Java內存模型
①Java內存模型分爲主內存和工做內存兩個部分,其中主內存存放變量,工做內存由每一個線程建立和管理,保存被該線程使用到的變量的主內存的副本拷貝。變量從主內存複製到工做內存,順序執行read和load操做,變量從工做內存同步到主內存的時候,順序執行store和write操做。
對於volatile變量在各個線程的一致性:在各個線程的工做內存中,volatile存在不一致的狀況,但在每次使用前都會刷新,執行引擎看不到不一致的狀況,所以能夠認爲不存在一致性問題。
②原子性、可見性和有序性
③先行發生原則
十一、Java垃圾回收機制
Java的垃圾回收機制是Java虛擬機提供的能力,用於在空閒時間以不定時的方式動態回收無任何引用的對象佔據的內存空間。
System.gc();
Runtime.getRuntime().gc();
上面的方法調用時用於顯式通知JVM能夠進行一次垃圾回收,但真正垃圾回收機制具體在什麼時間點開始發生動做這一樣是不可預料的,這和搶佔式的線程在發生做用時的原理同樣。
十二、類加載器,類加載時機
類初始化的時機,有且僅有四個:
A、遇到new、getstatic、putstatic、invokestatic這四條字節碼指令的時候。
B、使用java.lang.reflect進行反射調用的時候。
C、當初始化一個類的時候,發現其父類尚未初始化,那麼先去初始化它的父類。
D、當虛擬機啓動的時候,須要初始化main函數所在的類。
1三、 Java IO和NIO區別
①NIO操做直接緩存區,直接與OS交互,Selector IO複用機制。
IO NIO
面向流 面向緩衝
阻塞IO 非阻塞IO
無 選擇器
Selector:Java NIO的選擇器容許一個單獨的線程來監視多個輸入通道,你能夠註冊多個通道使用一個選擇器,而後使用一個單獨的線程來「選擇」通道:這些通道里已經有能夠處理的輸入,或者選擇已準備寫入的通道。這種選擇機制,使得一個單獨的線程很容易來管理多個通道。
②NIO與Netty:A、NIO的類庫和API複雜,使用麻煩,須要熟練使用Selector、ServerSocketChannel、SOcketChannel、ByteBuffer等。B、NIO涉及到Reactor模式,須要瞭解Java多線程和網絡編程。C、JDKNIO Bug-epoll bug容易致使Selector空輪詢,最終致使CPU100%佔用,雖然JDK1.6 update18修復了這個問題,可是直到JDK1.7問題依然存在,只是下降了發生的機率。
③Netty的優勢:A、API簡單,開發門檻低;B、功能強大,預置了多種解碼功能,支持多種主流協議;C、能夠經過ChannelHandler對通訊框架進行靈活的擴展;D、性能高,Netty的綜合性能是最好的;E、Netty修復了一經發現了全部的JDKNIO BUG,成熟,穩定。
同步和異步的概念描述的是用戶線程與內核的交互方式:同步是指用戶線程發起IO請求後須要等待或者輪詢內核IO操做完成後才能繼續執行;而異步是指用戶線程發起IO請求後仍繼續執行,當內核IO操做完成後會通知用戶線程,或者調用用戶線程註冊的回調函數。
引伸:
Java中IO的種類和應用場景:
A、同步阻塞式:BIO。用於鏈接數目較小且固定的架構,對服務器資源佔用高。
B、僞異步IO變成:線程池和任務隊列。
C、NIO編程:a、緩衝徐ByteBuffer;b、通道channel全雙工,同時用於讀寫;c、多路複用器selector。用於鏈接數目多且較短的架構,如聊天服務器等,可是編程複雜,存在epoll bug,致使Selector空輪詢,直至CPU佔用達到100%,雖然在JDK1.6 update18中有對這個bug的修復,可是在JDK1.7中依然可能會出現這個問題,只是下降了bug出現的機率。
D、AIO編程:用於鏈接數目多且較長的架構,如相冊服務器等,充分調用OS參與併發操做,基於JDK1.7。
阻塞和非阻塞的概念描述的是用戶線程調用內核IO操做的方式:阻塞是指IO操做須要完全完成後才返回到用戶空間;而非阻塞是指IO操做被調用後當即返回給用戶一個狀態值,無需等到IO操做完全完成。
1四、Java鎖機制
①synchronized:把代碼塊聲明爲 synchronized,有兩個重要後果,一般是指該代碼具備 原子性和可見性。做用:A、當兩個併發線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內只能有一個線程獲得執行。另外一個線程必須等待當前線程執行完這個代碼塊之後才能執行該代碼塊。B、當一個線程訪問object的一個synchronized(this)同步代碼塊時,另外一個線程仍然能夠訪問該object中的非synchronized(this)同步代碼塊。C、尤爲關鍵的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其餘線程對object中全部其它synchronized(this)同步代碼塊的訪問將被阻塞。
A、原子性:原子性意味着個時刻,只有一個線程可以執行一段代碼,這段代碼經過一個monitor object保護。從而防止多個線程在更新共享狀態時相互衝突。
B、可見性:可見性則更爲微妙,它要對付內存緩存和編譯器優化的各類反常行爲。它必須確保釋放鎖以前對共享數據作出的更改對於隨後得到該鎖的另外一個線程是可見的。
C、volatile只保證可見性和禁止重排序,不保證原子性。
②synchronized限制:
A.它沒法中斷一個正在等候得到鎖的線程;
B.也沒法經過投票獲得鎖,若是不想等下去,也就無法獲得鎖;
C.同步還要求鎖的釋放只能在與得到鎖所在的堆棧幀相同的堆棧幀中進行,多數狀況下,這沒問題(並且與異常處理交互得很好),可是,確實存在一些非塊結構的鎖定更合適的狀況。
③java.util.concurrent.lock:
ReentrantLock 類實現了Lock,它擁有與synchronized 相同的併發性和內存語義,可是添加了相似鎖投票、定時鎖等候和可中斷鎖等候的一些特性。此外,它還提供了在激烈爭用狀況下更佳的性能。
用sychronized修飾的方法或者語句塊在代碼執行完以後鎖自動釋放,而是用Lock須要咱們手動釋放鎖,因此爲了保證鎖最終被釋放(發生異常狀況),要把互斥區放在try內,釋放鎖放在finally內。
④ReentrantWriteReadLock中的ReadLock和WWriteLock,在全爲讀時實現併發讀,併發讀寫或併發寫時候加鎖。
總結:synchronized是Java原語,阻塞的,競爭鎖機制;新鎖更加面向對象,而且支持中斷和支持公平鎖。
1五、Java基本數據類型
boolean(1)、byte(8)、char(16)、short(16)、int(32)、float(32)、long(64)、double(64)
1六、Java內存模型
①特色:原子性、可見性、有序性。
A、原子性:read、load、use、store、write,synchronized關鍵字保證原子性
B、可見性:synchronized、volatile、final保證可見性
C、有序性:synchronized保證有序性
1七、設計模式
①分類:
建立型模式,共五種:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式。
結構型模式,共七種:適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
行爲型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。
其實還有兩類:併發型模式和線程池模式。
②設計模式6大原則:
A、開閉原則(Open Close Principle)
開閉原則就是說對擴展開放,對修改關閉。在程序須要進行拓展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。因此一句話歸納就是:爲了使程序的擴展性好,易於維護和升級。想要達到這樣的效果,咱們須要使用接口和抽象類,後面的具體設計中咱們會提到這點。
B、里氏代換原則(Liskov Substitution Principle)
里氏代換原則(Liskov Substitution Principle LSP)面向對象設計的基本原則之一。 里氏代換原則中說,任何基類能夠出現的地方,子類必定能夠出現。 LSP是繼承複用的基石,只有當衍生類能夠替換掉基類,軟件單位的功能不受到影響時,基類才能真正被複用,而衍生類也可以在基類的基礎上增長新的行爲。里氏代換原則是對「開-閉」原則的補充。實現「開-閉」原則的關鍵步驟就是抽象化。而基類與子類的繼承關係就是抽象化的具體實現,因此里氏代換原則是對實現抽象化的具體步驟的規範。—— From Baidu 百科
C、依賴倒轉原則(Dependence Inversion Principle)
這個是開閉原則的基礎,具體內容:真對接口編程,依賴於抽象而不依賴於具體。
D、接口隔離原則(Interface Segregation Principle)
這個原則的意思是:使用多個隔離的接口,比使用單個接口要好。仍是一個下降類之間的耦合度的意思,從這兒咱們看出,其實設計模式就是一個軟件的設計思想,從大型軟件架構出發,爲了升級和維護方便。因此上文中屢次出現:下降依賴,下降耦合。
F、迪米特法則(最少知道原則)(Demeter Principle)
爲何叫最少知道原則,就是說:一個實體應當儘可能少的與其餘實體之間發生相互做用,使得系統功能模塊相對獨立。
F、合成複用原則(Composite Reuse Principle)
原則是儘可能使用合成/聚合的方式,而不是使用繼承。
1八、Java反射
反射機制指的是程序在運行時可以獲取自身的信息。
爲何要用反射機制?直接建立對象不就能夠了嗎,這就涉及到了動態與靜態的概念,
靜態編譯:在編譯時肯定類型,綁定對象,即經過。
動態編譯:運行時肯定類型,綁定對象。動態編譯最大限度發揮了java的靈活性,體現了多態的應用,有以下降類之間的藕合性。
一句話,反射機制的優勢就是能夠實現動態建立對象和編譯,體現出很大的靈活性,特別是在J2EE的開發中
它的靈活性就表現的十分明顯。
做用:①首先得根據傳入的類的全名來建立Class對象。 ②得到類方法的方法。③ 得到類中屬性的方法。
缺點:①性能第一:反射包括了一些動態類型,因此JVM沒法對這些代碼進行優化。所以,反射操做的效率要比那些非反射操做低得多。咱們應該避免在常常被 執行的代碼或對性能要求很高的程序中使用反射。②安全限制:使用反射技術要求程序必須在一個沒有安全限制的環境中運行。若是一個程序必須在有安全限制的環境中運行,如Applet。③內部暴露:因爲反射容許代碼執行一些在正常狀況下不被容許的操做(好比訪問私有的屬性和方法),因此使用反射可能會致使意料以外的反作用--代碼有功能上的錯誤,下降可移植性。反射代碼破壞了抽象性,所以當平臺發生改變的時候,代碼的行爲就有可能也隨着變化。
1九、Java引用
①假設咱們在函數中寫了以下這個簡單的語句:
StringBuffer str= new StringBuffer("Hello world");
別看這個語句簡單,其實包含了以下三個步驟:
首先,new StringBuffer("Hello world")在堆裏申請了一坨內存,把建立好的StringBuffer對象放進去。其次,StringBuffer str聲明瞭一個指針。這個指針自己是存儲在棧上的(由於語句寫在函數中),能夠用來指向某個StringBuffer類型的對象。或者換一種說法,這個指針能夠用來保存某個StringBuffer對象的地址。最後,當中這個等於號(賦值符號)把二者關聯起來,也就是把剛申請的那一坨內存的地址保存成str的值,完成引用。
②final常量的問題
針對引用類型變量的final修飾符也是不少人搞混淆的地方。實際上final只是修飾指針的值(也就是限定指針保存的地址不能變)。至於該指針指向的對象,內容是否能變,那就管不着了。因此,對於以下語句:
final StringBuffer strConst = new StringBuffer();
你能夠修改它指向的對象的內容,好比:
strConst.append(" ");
可是不能修改它的值,好比:
strConst = null;
③傳參的問題:
例如:System.out.println(str);這個語句又是什麼意思捏?這時候就兩說了。
第一種理解:能夠認爲傳進函數的是str這個指針,指針說白了就是一個地址的值,說得再白一點,就是個整數。按照這種理解,就是傳值的方式。也就是說,參數傳遞的是指針自己,因此是傳值的。
第二種理解:能夠認爲傳進去的是StringBuffer對象,按照這種理解,就是傳引用方式了。由於咱們確實是把對象的地址(也就是引用)給傳了進去。
20、 線程、線程池:
①建立線程有兩種方式:繼承Thread或實現Runnable。Thread實現了Runnable接口,提供了一個空的run()方法,因此不管是繼承Thread仍是實現Runnable,都要有本身的run()方法。一個線程建立後就存在,調用start()方法就開始運行(執行run()方法),調用wait進入等待或調用sleep進入休眠期,順利運行完畢或休眠被中斷或運行過程當中出現異常而退出。
②wait和sleep比較:sleep方法有:sleep(long millis),sleep(long millis, long nanos),調用sleep方法後,當前線程進入休眠期,暫停執行,但該線程繼續擁有監視資源的全部權。到達休眠時間後線程將繼續執行,直到完成。若在休眠期另外一線程中斷該線程,則該線程退出。等待有其它的線程調用notify()或notifyAll()進入調度狀態,與其它線程共同爭奪監視。
③線程池:多線程技術主要解決處理器單元內多個線程執行的問題,它能夠顯著減小處理器單元的閒置時間,增長處理器單元的吞吐能力。一個線程池包括如下四個基本組成部分:
A、線程池管理器(ThreadPool):用於建立並管理線程池,包括建立線程池,銷燬線程池,添加新任務;
B、工做線程(PoolWorker):線程池中線程,在沒有任務時處於等待狀態,能夠循環的執行任務;
C、任務接口(Task):每一個任務必須實現的接口,以供工做線程調度任務的執行,它主要規定了任務的入口,任務執行完後的收尾工做,任務的執行狀態等;
D、任務隊列(taskQueue):用於存放沒有處理的任務。提供一種緩衝機制。
④線程池分類:
A、newFixedThreadPool 建立一個指定工做線程數量的線程池。
每當提交一個任務就建立一個工做線程,若是工做線程數量達到線程池初始的最大數,則將提交的任務存入到池隊列中。
B、newCachedThreadPool建立一個可緩存的線程池。
這種類型的線程池特色是:
1).工做線程的建立數量幾乎沒有限制(其實也有限制的,數目爲Interger.MAX_VALUE), 這樣可靈活的往線程池中添加線程。
2).若是長時間沒有往線程池中提交任務,即若是工做線程空閒了指定的時間(默認爲1分鐘),則該工做線程將自動終止。終止後,若是你又提交了新的任務,則線程池從新建立一個工做線程。
C、newSingleThreadExecutor建立一個單線程化的Executor,即只建立惟一的工做者線程來執行任務,若是這個線程異常結束,會有另外一個取代它,保證順序執行(我以爲這點是它的特點)。
單工做線程最大的特色是可保證順序地執行各個任務,而且在任意給定的時間不會有多個線程是活動的。
D、newScheduleThreadPool 建立一個定長的線程池,並且支持定時的以及週期性的任務執行,相似於Timer。
⑤Executors類,提供了一系列靜態工廠方法用於創先線程池,返回的線程池都實現了ExecutorService接口。
⑥線程池參數:
A、corePoolSize(線程池的基本大小)
B、runnableTaskQueue(任務隊列):用於保存等待執行的任務的阻塞隊列。
1)LinkedBlockingQueue:一個基於鏈表結構的阻塞隊列,此隊列按FIFO (先進先出) 排序元素,吞吐量一般要高於ArrayBlockingQueue。靜態工廠方法Executors.newFixedThreadPool()使用了這個隊列。
2)SynchronousQueue:一個不存儲元素的阻塞隊列。每一個插入操做必須等到另外一個線程調用移除操做,不然插入操做一直處於阻塞狀態,吞吐量一般要高於LinkedBlockingQueue,靜態工廠方法Executors.newCachedThreadPool使用了這個隊列。
3)PriorityBlockingQueue:一個具備優先級的無限阻塞隊列。
C、maximumPoolSize(線程池最大大小):線程池容許建立的最大線程數。
D、ThreadFactory:用於設置建立線程的工廠,能夠經過線程工廠給每一個建立出來的線程設置更有意義的名字。
E、RejectedExecutionHandler(飽和策略):當隊列和線程池都滿了,說明線程池處於飽和狀態,那麼必須採起一種策略處理提交的新任務。這個策略默認狀況下是AbortPolicy,表示沒法處理新任務時拋出異常。如下是JDK1.5提供的四種策略:
1)AbortPolicy:直接拋出異常。
2)CallerRunsPolicy:只用調用者所在線程來運行任務。
3)DiscardOldestPolicy:丟棄隊列裏最近的一個任務,並執行當前任務。
4)DiscardPolicy:不處理,丟棄掉。
5)固然也能夠根據應用場景須要來實現RejectedExecutionHandler接口自定義策略。如記錄日誌或持久化不能處理的任務。
F、keepAliveTime(線程活動保持時間):線程池的工做線程空閒後,保持存活的時間。因此若是任務不少,而且每一個任務執行的時間比較短,能夠調大這個時間,提升線程的利用率。
G、TimeUnit(線程活動保持時間的單位):可選的單位有天(DAYS),小時(HOURS),分鐘(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。
2一、J2EE的13種規範
(1)、JDBC(java Database Connectivity):
JDBC API爲訪問不一樣的數據庫提供了一種統一的途徑,就像ODBC同樣,JDBC對開發者屏蔽了一些細節問題,同時,JDBC對數據庫的訪問也具備平臺無關性。
(2)、JNDI(Java Name and Directory Interface):
JNDI API 被用於執行名字和目錄服務。它提供了一致的模型用來存取和操做企業級的資源如DNS和LDAP,本地文件系統,或應用服務器中的對象。
(3)、EJB(Enterprise JavaBean):
J2ee技術之因此贏得全體普遍重視的緣由之一就是EJB,他們提供了一個框架開發和實施分佈式商務邏輯,由此很顯著簡化了具備可伸縮性和高度複雜的企業級應用開發。EJB規範定義了EJB組件什麼時候如何與他們的容器繼續擰交互做用。容器負責提供公用的服務,例如目錄服務、事務管理、安全性、資源緩衝池以及容錯性。可是注意的是,EJB並非J2EE的惟一途徑。正是因爲EJB的開放性,使得有的廠商可以以一種和EJB平行的方式來達到一樣的目的。
(4)、RMI(RemoteMethod Invoke):remote(遙遠的) invoke(調用):
正如其名字所表示的那樣,RMI協議調用遠程對象上方法。它使用了序列化方式在客戶端和服務器端傳遞數據。RMI是一種被EJB使用的更底層的協議。
(5)、Java IDL(接口定義語言)/CORBA:公共對象請求代理結構(Common Object Request Breaker Architecture):
在java IDL的支持下,開發人員能夠將Java和CORBA集成在一塊兒。他們能夠建立Java對象並使之能夠在CORBA ORB中展開,或者他們還能夠建立Java類並作爲和其餘ORB一塊兒展開的CORBA對象客戶。後一種方法提供了另一種途徑,經過它能夠被用於你的新的應用和舊系統相集成。
(6)、JSP(Java Server Pages):
Jsp頁面由html代碼和嵌入其中的Java新代碼所組成。服務器在頁面被客戶端所請求之後對這些java代碼進行處理,而後將生成的html頁面返回給客戶端的瀏覽器。
(7)、Java Servlet:
servlet是一種小型的java程序,它擴展了web服務器的功能。做爲一種服務器端的應用,當被請求時開始執行,這和CGI Perl腳本很類似。Servlet提供的功能大多和jsp相似,不過實現方式不一樣。JSP經過大多數的html代碼中嵌入少許的java代碼,而servlet所有由java寫成並生成相應的html。
(8)、XML(Extensible Markup Language):
XML是一種能夠用來定義其餘標記語言的語言。它被用來在不一樣的商務過程當中共享數據。XML的發展和Java是互相獨立的,可是,它和java具備相同目標正是平臺獨立。經過java和xml的組合,咱們能夠獲得一個完美的具備平臺獨立性的解決方案。
(9)、JMS(Java Message Service):
Ms是用於和麪向消息的中間件相互通訊的應用程序接口(API)。它既支持點對點的域,有支持發佈/訂閱類型的域,而且提供對下列類型的支持:經承認的消息傳遞,事務性消息傳遞,一致性消息和具備持久性的訂閱者的支持。JMS還提供了另外一種方式對您的應用與舊的後臺系統相集成。
(10)、JTA(Java Transaction Architecture):
JTA定義了一種標準API,應用系統由此能夠訪問各類事務監控。
(11)、JTS(Java Transaction Service):
JTS是CORBA OTS事務監控的基本實現。JTS規定了事務管理器的實現方式。該事務管理器是在高層支持Java Transaction API(JTA)規範,而且在較底層實現OMG OTS specification 的java映像。JTS事務管理器爲應用服務器、資源管理器、獨立的應用以及通訊資源管理器提供了事務服務。
(12)、JavaMail:
JavaMail是用於存取郵件服務的API,它提供了一套郵件服務器的抽象類。不只支持SMTP服務器,也支持IMAP服務器。
(13)、JAF(JavaBeans Activation Framework):
JavaMail利用JAF來處理MIME編碼的郵件附件。MIME的字節流能夠被轉換成java對象,或者轉換自Java對象。大多數應用均可以不須要直接使用JAF。
一、web服務器nginx和apache的對比分析
①nginx相對於apache的優勢:
輕量級,一樣起web 服務,比apache 佔用更少的內存及資源 ,抗併發,nginx 處理請求是異步非阻塞的,而apache 則是阻塞型的,在高併發下nginx 能保持低資源低消耗高性能,高度模塊化的設計,編寫模塊相對簡單。
apache相對於nginx 的優勢:A.rewrite ,比nginx 的rewrite 強大;B.動態頁面,模塊超多,基本想到的均可以找到;C.少bug ,nginx 的bug 相對較多;D.超穩定.
通常來講,須要性能的web 服務,用nginx 。若是不須要性能只求穩定,那就apache.
②做爲 Web 服務器:相比 Apache,Nginx 使用更少的資源,支持更多的併發鏈接,體現更高的效率。Nginx採用C進行編寫, 不管是系統資源開銷仍是CPU使用效率都比 Perlbal 要好不少.
③Nginx 配置簡潔,Apache 複雜。Nginx 靜態處理性能比 Apache 高 3倍以上,Apache 對 PHP 支持比較簡單,Nginx 須要配合其餘後端用。Apache 的組件比 Nginx 多,如今 Nginx 纔是Web 服務器的首選。
④最核心的區別在於apache是同步多進程模型,一個鏈接對應一個進程;nginx是異步的,多個鏈接(萬級別)能夠對應一個進程。
⑤nginx處理靜態文件好,耗費內存少.但無疑apache仍然是目前的主流,有不少豐富的特性.因此還須要搭配着來.固然若是能肯定nginx就適合需求,那麼使用nginx會是更經濟的方式。
⑥nginx處理動態請求是雞肋,通常動態請求要apache去作,nginx只適合靜態和反向。
⑦Nginx優於apache的主要兩點:A.Nginx自己就是一個反向代理服務器 B.Nginx支持7層負載均衡;其餘的固然,Nginx可能會比 apache支持更高的併發。
一、數據庫優化:
①方法:MySQL能夠建分表,讀寫分離,建索引,通常常常更新的字段不適合建索引,建索引會下降數據非查詢操做的效率。主鍵是一種特殊的索引。
②致使索引失效的狀況:
A、若是條件中有or,即便其中有條件帶索引也不會使用到。
B、對於多列索引,不是使用的第一部分,則不會使用索引。
C、like查詢是以%開頭,而不是以%結尾的。
D、若是索引列類型是字符串,必定要在條件中將數據使用引號引用起來,不然不使用索引。
E、若是mysql估計使用全表掃描要比使用索引快,則不使用索引。
二、MySQL引擎的種類和區別
①種類:MyISAM、InnoDB、MEMORY、MERGE、Archive、Blackhole、CSV、Federate、Merge、NDB集羣引擎,第三方引擎:OLTP類引擎、面向列的存儲引擎、社區存儲引擎。
②區別:
A、MyISAM是MySQL5.1及以前的默認存儲引擎。MyISAM不支持事務、也不支持外鍵,但其訪問速度快,對事務完整性沒有要求。MyISAM表還支持3中不一樣的存儲格式:
1 靜態表
2 動態表
3 壓縮表
B、InnoDB存儲引擎提供了具備提交、回滾和崩潰恢復能力的事務安全。可是比起MyISAM存儲引擎,InnoDB寫的處理效率差一些而且會佔用更多的磁盤空間以保留數據和索引。 InnoDB存儲方式爲兩種:1 使用共享表空間存儲 2 使用多表空間
C、MEMORY存儲引擎使用存在內存中的內容來建立表。每一個MEMORY表只實際對應一個磁盤文件。MEMORY類型的表訪問很是得快,由於它的數據是放在內存中的,而且默認使用HASH索引。可是一旦服務關閉,表中的數據就會丟失掉。
D、MERGE存儲引擎是一組MyISAM表的組合,這些MyISAM表必須結構徹底相同。MERGE表自己沒有數據,對MERGE類型的表進行查詢、更新、刪除的操做,就是對內部的MyISAM表進行的。
三、數據庫事務
(1)四個特性:ACID,原子性,一致性,隔離性,持久性。
(2)四個隔離級別:
√: 可能出現 ×: 不會出現
髒讀 | 不可重複讀 | 幻讀 | |
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |
Read Uncommitted(讀取未提交內容)
在該隔離級別,全部事務均可以看到其餘未提交事務的執行結果。本隔離級別不多用於實際應用,由於它的性能也不比其餘級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)。
Read Committed(讀取提交內容)
這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它知足了隔離的簡單定義:一個事務只能看見已經提交事務所作的改變。這種隔離級別 也支持所謂的不可重複讀(Nonrepeatable Read),由於同一事務的其餘實例在該實例處理其間可能會有新的commit,因此同一select可能返回不一樣結果。
Repeatable Read(可重讀)
這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到一樣的數據行。不過理論上,這會致使另外一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的「幻影」 行。InnoDB和Falcon存儲引擎經過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。
Serializable(可串行化)
這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭。
這四種隔離級別採起不一樣的鎖類型來實現,若讀取的是同一個數據的話,就容易發生問題。例如:
i. 髒讀(Drity Read):某個事務已更新一份數據,另外一個事務在此時讀取了同一份數據,因爲某些緣由,前一個RollBack了操做,則後一個事務所讀取的數據就會是不正確的。
ii. 不可重複讀(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,這多是兩次查詢過程當中間插入了一個事務更新的原有的數據。
iii. 幻讀(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,例若有一個事務查詢了幾列(Row)數據,而另外一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的。
(3)一致性處理:
A、開啓事務。B、申請寫權限,也就是給對象(表或記錄)加鎖。C、假如失敗,則結束事務,過一會重試。D、假如成功,也就是給對象加鎖成功,防止其餘用戶再用一樣的方式打開。E、進行編輯操做。F、寫入所進行的編輯結果。G、假如寫入成功,則提交事務,完成操做。 H、假如寫入失敗,則回滾事務,取消提交。I、(G、H)兩步操做已釋放了鎖定的對象,恢復到操做前的狀態。
(4)基於事務的數據庫引擎的選型:若是考慮到事務,推薦選用MySQL INNODB引擎;若是考慮速度,建議考慮MySQL MyISAM引擎,而且須要在代碼層面作比較複雜的處理,如經過多線程、異步、非阻塞等方式對數據庫進行清理,同時須要信號量、欄柵、數據庫標誌位等工具保證數據一致性。
四、海量數據處理
(1)數據庫擴展:
①縱向擴展:基於業務的高度隔離性和數據的安全性,對業務和數據進行合理的切分,進行主-備機分離,主-主同步,主-從同步(對於MySQL數據庫是單向異步同步機制),主-從熱備等操做。
②橫向擴展:對數據表進行橫向切分,按必定的規則(hash取模分、user_id尾數、自定義算法等)對數據表進行橫向切分。
關於數據庫架構和擴展方面的文章請見:Mysql在大型網站的應用架構演變。
(2)分佈式數據方案:
①提供分庫規則和路由規則(RouteRule簡稱RR),將上面的說明中提到的三中切分規則直接內嵌入本系統,具體的嵌入方式在接下來的內容中進行詳細的說明和論述;
②引入集羣(Group)的概念,保證數據的高可用性;
③引入負載均衡策略(LoadBalancePolicy簡稱LB);
④引入集羣節點可用性探測機制,對單點機器的可用性進行定時的偵測,以保證LB策略的正確實施,以確保系統的高度穩定性;
⑤引入讀/寫分離,提升數據的查詢速度。
具體描述請參見博文:MySQL 海量數據的存儲和訪問解決方案。
(3)數據庫切分策略介紹,請見博文:數據庫Sharding的基本思想和切分策略。
(4)隨着數據量隨着業務的發展不斷增大,傳統的關係型數據庫RDB已經沒法知足須要,這時須要引入新的海量數據處理解決方案:Apache HBase。
一、Struts2
①工做原理
A、在Struts2框架中的處理大概分爲如下幾個步驟:
1)客戶端初始化一個指向Servlet容器(例如Tomcat)的請求
2)這個請求通過一系列的過濾器(Filter)(這些過濾器中有一個叫作ActionContextCleanUp的可選過濾器,這個過濾器對於Struts2和其餘框架的集成頗有幫助,例如:SiteMesh Plugin)
3)接着FilterDispatcher被調用,FilterDispatcher詢問ActionMapper來決定這個請是否須要調用某個Action
4)若是ActionMapper決定須要調用某個Action,FilterDispatcher把請求的處理交給ActionProxy
5)ActionProxy經過Configuration Manager詢問框架的配置文件,找到須要調用的Action類
6)ActionProxy建立一個ActionInvocation的實例。
7)ActionInvocation實例使用命名模式來調用,在調用Action的過程先後,涉及到相關攔截器(Intercepter)的調用。
8)一旦Action執行完畢,ActionInvocation負責根據struts.xml中的配置找到對應的返回結果。返回結果一般是(但不老是,也可 能是另外的一個Action鏈)一個須要被表示的JSP或者FreeMarker的模版。在表示的過程當中能夠使用Struts2 框架中繼承的標籤。在這個過程當中須要涉及到ActionMapper。
②工做流程:
1)客戶端在瀏覽器中輸入一個url地址。
2)這個url請求經過http協議發送給tomcat。
3)tomcat根據url找到對應項目裏面的web.xml文件。
4)在web.xml裏面會發現有struts2的配置。
5)而後會找到struts2對應的struts.xml配置文件。
6)根據url解析struts.xml配置文件就會找到對應的class。
7)調用完class返回一個字String,根據struts.xml返回到對應的jsp。
二、spring原理
①IoC(Inversion of control): 控制反轉,依賴注入
1)IoC:
概念:控制權由對象自己轉向容器;由容器根據配置文件去建立實例並建立各個實例之間的依賴關係
2)依賴IoC容器負責管理bean,有兩種,一種是BeanFactory,另外一種是ApplicationContext,可是ApplicationContext繼承與BeanFactory。
核心:bean工廠;在Spring中,bean工廠建立的各個實例稱做bean
②AOP(Aspect-Oriented Programming): 面向方面編程
1)代理的兩種方式:
靜態代理:
針對每一個具體類分別編寫代理類;
針對一個接口編寫一個代理類;
動態代理:
針對一個方面編寫一個InvocationHandler,而後借用JDK反射包中的Proxy類爲各類接口動態生成相應的代理類
2) AOP的主要原理:動態代理
實現:有兩種:JDK Proxy和Cglib,Spring規定對於有接口的類用JDK Proxy,對於無接口和抽象類用Cglib,雖然Cglib都可以代理,可是Cglib複雜,效率低。可是Cglib有例外,就是代理的類中不能是final修飾的類或者類中有final方法。
三、Spring、Struts二、Servlet對比
①Servlet原理:Tomcat 的容器等級中,Context 容器是直接管理 Servlet 在容器中的包裝類 Wrapper,因此 Context 容器如何運行將直接影響 Servlet 的工做方式。
A、Servlet生命週期詳解
Servlet的生命週期能夠分爲四個階段,即裝載類及建立實例階段、初始化階段、服務階段和實例銷燬階段。下面針對每一個階段的編程任務及注意事項進行詳細的說明。
B、Servlet建立過程
在默認狀況下Servlet實例是在第一個請求到來的時候建立,之後複用。一旦Servlet實例被建立,Web服務器會自動調用init(ServletConfig config)方法來初始化該Servlet。其中方法參數config中包含了Servlet的配置信息,好比初始化參數,該對象由服務器建立。init方法在Servlet生命週期中只執行一次,並且該方法執行在單線程的環境下,所以開發者不用考慮線程安全的問題。
C、服務
一旦Servlet實例成功建立及初始化,該Servlet實例就能夠被服務器用來服務於客戶端的請求並生成響應。在服務階段Web服務器會調用該實例的service(ServletRequest request,ServletResponse response)方法,request對象和response對象有服務器建立並傳給Servlet實例。request對象封裝了客戶端發往服務器端的信息,response對象封裝了服務器發往客戶端的信息。
爲了提升效率,Servlet規範要求一個Servlet實例必須可以同時服務於多個客戶端請求,即service()方法運行在多線程的環境下,Servlet開發者必須保證該方法的線程安全性。
Serlvet接口只定義了一個服務方法就是service,而HttpServlet類實現了該方法而且要求調用下列的方法之一:
doGet:處理GET請求
doPost:處理POST請求
當發出客戶端請求的時候,調用service 方法並傳遞一個請求和響應對象。Servlet首先判斷該請求是GET 操做仍是POST 操做。而後它調用下面的一個方法:doGet 或 doPost。若是請求是GET就調用doGet方法,若是請求是POST就調用doPost方法。
②對比:Spring主要有IoC和AOP,Spring中IoC管理的bean爲單例模式的,能夠配置成原型模式。若是用Spring管理struts2的bean,必需要設置成原型模式,由於struts2封裝來了servlet,隔離了servlet的特性,Action不一樣於Spring,已是原型模式了。
四、memcached和redis區別
①Memcached出現於2003年,key支持250bytes,value支持1MB;redis出現於2009年,key和value都是支持512MB的。
持久化方面,memcached過時失效,redis能夠緩存回收(6種回收機制),有存儲,可算爲NOSQL,有優化,支持190多種命令。
集羣方面,memcached不支持集羣,基於兩次哈希,第一次哈希找到服務器節點,第二次哈希找到存儲的值。
1)Redis不只僅支持簡單的k/v類型的數據,同時還提供list,set,hash等數據結構的存儲。
2)Redis支持數據的備份,即master-slave模式的數據備份。
3)Redis支持數據的持久化,能夠將內存中的數據保持在磁盤中,重啓的時候能夠再次加載進行使用。
Redis只會緩存全部的key的信息,若是Redis發現內存的使用量超過了某一個閥值,將觸發swap的操做,Redis根據「swappability= age*log(size_in_memory)」計算出哪些key對應的value須要swap到磁盤。而後再將這些key對應的value持久化到磁盤中,同時在內存中清除。這種特性使得Redis能夠保持超過其機器自己內存大小的數據。固然,機器自己的內存必需要可以保持全部的key,畢竟這些數據是不會進行swap操做的。
②memcached、redis和mongoDB三者之間的對比:
1)性能
都比較高,性能對咱們來講應該都不是瓶頸
整體來說,TPS(每秒事務處理量)方面redis和memcache差很少,要大於mongodb
2)操做的便利性
memcache數據結構單一
redis豐富一些,數據操做方面,redis更好一些,較少的網絡IO次數
mongodb支持豐富的數據表達,索引,最相似關係型數據庫,支持的查詢語言很是豐富
3)內存空間的大小和數據量的大小
redis在2.0版本後增長了本身的VM特性,突破物理內存的限制;能夠對key value設置過時時間(相似memcache)
memcache能夠修改最大可用內存,採用LRU算法
mongoDB適合大數據量的存儲,依賴操做系統VM作內存管理,吃內存也比較厲害,服務不要和別的服務在一塊兒
4)可用性(單點問題)
對於單點問題,
redis,依賴客戶端來實現分佈式讀寫;主從複製時,每次從節點從新鏈接主節點都要依賴整個快照,無增量複製,因性能和效率問題,
因此單點問題比較複雜;不支持自動sharding,須要依賴程序設定一致hash 機制。
一種替代方案是,不用redis自己的複製機制,採用本身作主動複製(多份存儲),或者改爲增量複製的方式(須要本身實現),一致性問題和性能的權衡
Memcache自己沒有數據冗餘機制,也不必;對於故障預防,採用依賴成熟的hash或者環狀的算法,解決單點故障引發的抖動問題。
mongoDB支持master-slave,replicaset(內部採用paxos選舉算法,自動故障恢復),auto sharding機制,對客戶端屏蔽了故障轉移和切分機制。
5)可靠性(持久化)
對於數據持久化和數據恢復,
redis支持(快照、AOF):依賴快照進行持久化,aof加強了可靠性的同時,對性能有所影響;memcache不支持,一般用在作緩存,提高性能;MongoDB從1.8版本開始採用binlog方式支持持久化的可靠性。
6)數據一致性(事務支持)
Memcache 在併發場景下,用cas保證一致性。
redis事務支持比較弱,只能保證事務中的每一個操做連續執行。
mongoDB不支持事務
7)數據分析
mongoDB內置了數據分析的功能(mapreduce),其餘不支持。
8)應用場景
redis:數據量較小的更性能操做和運算上。
memcache:用於在動態系統中減小數據庫負載,提高性能;作緩存,提升性能(適合讀多寫少,對於數據量比較大,能夠採用sharding)。
MongoDB:主要解決海量數據的訪問效率問題。
五、設計一個緩存
A、過時時間
B、多態實現訪問量
C、弱引用、軟引用。
D、WeakHashMap的使用。
緩存技術的實現原理:LRU(Least Recently Used)緩存技術
能夠使用兩個標準的數據結構來實現,Map和Queue。由於須要支持多線程,須要使用實現了java.util.concurrent.*的Map和Queue。主要思路是使用一個Queue來維護FIFO和Map來對數據進行排序,當向緩存添加新的元素時,共有如下三種可能:
①若是該元素已經在Cache中存在(Map),咱們會從Queue中刪除元素並將其添加到Queue的第一個位置;
②若是緩存已經沒法知足新增新的元素,咱們會從Queue和Map中刪除最後面的那個元素並把新元素添加進來;
③同時在Map和Queue中增長新的元素。
參考代碼:
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; public class LRUCache<K, V> { // LRU 緩存的最大容量. private final int capacity; // 用來保持最近使用的元素的 Queue. private ConcurrentLinkedQueue<K> queue; private ConcurrentHashMap<K, V> map; /** * 初始化 LRU 緩存 * * @param capacity */ public LRUCache(final int capacity) { this.capacity = capacity; this.queue = new ConcurrentLinkedQueue<K>(); this.map = new ConcurrentHashMap<K, V>(capacity); } /** * 檢查該元素釋放在緩存中存在,若是不存在則返回 null * * @param key * @return */ public V get(final K key) { return map.get(key); } /** * 將元素添加到 LRU 緩存。若是 Key 已存在,則將其放到緩存的第一位置 * * @param key * @param value * @throws NullPointerException */ public synchronized void put(final K key, final V value) { if (key == null || value == null) { throw new NullPointerException(); } if (map.containsKey(key)) { queue.remove(key); } while (queue.size() >= capacity) { K expiredKey = queue.poll(); if (expiredKey != null) { map.remove(expiredKey); } } queue.add(key); map.put(key, value); } }
六、RPC
七、序列化
八、新技術
(1)Netty:
Netty是由JBOSS提供的一個java開源框架。Netty提供異步的、事件驅動的網絡應用程序框架和工具,用以快速開發高性能、高可靠性的網絡服務器和客戶端程序。 也就是說,Netty 是一個基於NIO的客戶,服務器端編程框架,使用Netty 能夠確保你快速和簡單的開發出一個網絡應用,例如實現了某種協議的客戶,服務端應用。Netty至關簡化和流線化了網絡應用的編程開發過程,例如,TCP和UDP的socket服務開發。 「快速」和「簡單」並不意味着會讓你的最終應用產生維護性或性能上的問題。Netty 是一個吸取了多種協議的實現經驗,這些協議包括FTP,SMTP,HTTP,各類二進制,文本協議,並通過至關精心設計的項目,最終,Netty 成功的找到了一種方式,在保證易於開發的同時還保證了其應用的性能,穩定性和伸縮性。
(2)MongoDB:
Mongo DB 是目前在IT行業很是流行的一種非關係型數據庫(NoSql),其靈活的數據存儲方式備受當前IT從業人員的青睞。Mongo DB很好的實現了面向對象的思想(OO思想),在Mongo DB中 每一條記錄都是一個Document對象。Mongo DB最大的優點在於全部的數據持久操做都無需開發人員手動編寫SQL語句,直接調用方法就能夠輕鬆的實現CRUD操做。
(3)Hadoop:
Hadoop是一個由Apache基金會所開發的分佈式系統基礎架構。 用戶能夠在不瞭解分佈式底層細節的狀況下,開發分佈式程序。充分利用集羣的威力進行高速運算和存儲。Hadoop實現了一個分佈式文件系統(Hadoop Distributed File System),簡稱HDFS。HDFS有高容錯性的特色,而且設計用來部署在低廉的(low-cost)硬件上;並且它提供高吞吐量(high throughput)來訪問應用程序的數據,適合那些有着超大數據集(large data set)的應用程序。HDFS放寬了(relax)POSIX的要求,能夠以流的形式訪問(streaming access)文件系統中的數據。 Hadoop的框架最核心的設計就是:HDFS和MapReduce。HDFS爲海量的數據提供了存儲,則MapReduce爲海量的數據提供了計算。
(4)Solr:
Solr是一個高性能,採用Java5開發,SolrSolr基於Lucene的全文搜索服務器。同時對其進行了擴展,提供了比Lucene更爲豐富的查詢語言,同時實現了可配置、可擴展並對查詢性能進行了優化,而且提供了一個完善的功能管理界面,是一款很是優秀的全文搜索引擎。
(5)ActiveMQ:
ActiveMQ 是Apache出品,最流行的,能力強勁的開源消息總線。ActiveMQ 是一個徹底支持JMS1.1和J2EE 1.4規範的 JMS Provider實現,儘管JMS規範出臺已是好久的事情了,可是JMS在當今的J2EE應用中間仍然扮演着特殊的地位。
(6)Velocity:Velocity是一個基於java的模板引擎(template engine)。它容許任何人僅僅使用簡單的模板語言(template language)來引用由java代碼定義的對象。
(7)Openfire :Openfire 採用Java開發,開源的實時協做(RTC)服務器基於XMPP(Jabber)協議。Openfire安裝和使用都很是簡單,並利用Web進行管理。單臺服務器可支持上萬併發用戶。
(8)Node.js:
Node.js是一個基於Chrome JavaScript運行時創建的平臺, 用於方便地搭建響應速度快、易於擴展的網絡應用。Node.js 使用事件驅動, 非阻塞I/O 模型而得以輕量和高效,很是適合在分佈式設備上運行的數據密集型的實時應用。 V8引擎執行Javascript的速度很是快,性能很是好。 Node是一個Javascript運行環境(runtime)。實際上它是對Google V8引擎進行了封裝。V8引 擎執行Javascript的速度很是快,性能很是好。Node對一些特殊用例進行了優化,提供了替代的API,使得V8在非瀏覽器環境下運行得更好。
(9)Ruby on Rails:
Ruby on Rails 是一個能夠使你開發,部署,維護 web 應用程序變得簡單的框架。ruby on rails使用的實時映射技術和元編程技術,免去了開發人員在開發過程當中編寫大量樣板文件代碼的煩惱。在少數須要使用樣板文件代碼的時候,開發人員能夠經過ruby on rails內建的生成器腳本實時建立,而再也不是經過手工編寫。rails的這個特色能夠使開發人員更專一於系統的邏輯結構,而沒必要爲一些瑣碎的細節所煩擾。
(10)Docker:
Docker 是一個開源的應用容器引擎,讓開發者能夠打包他們的應用以及依賴包到一個可移植的容器中,而後發佈到任何流行的 Linux 機器上,也能夠實現虛擬化。容器是徹底使用沙箱機制,相互之間不會有任何接口(相似 iPhone 的 app)。幾乎沒有性能開銷,能夠很容易地在機器和數據中心中運行。最重要的是,他們不依賴於任何語言、框架或包括系統。
(11)ElasticSearch:
ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分佈式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java開發的,並做爲Apache許可條款下的開放源碼發佈,是第二最流行的企業搜索引擎。設計用於雲計算中,可以達到實時搜索,穩定,可靠,快速,安裝使用方便。
(12)RESTful WebService:
RESTful WebService是比基於SOAP消息的WebService簡單的多的一種輕量級Web服務,RESTful WebService是沒有狀態的,發佈和調用都很是的輕鬆容易。
(13)Hessian:
Hessian是一個輕量級的remoting onhttp工具,使用簡單的方法提供了RMI的功能。 相比WebService,Hessian更簡單、快捷。採用的是二進制RPC協議,由於採用的是二進制協議,因此它很適合於發送二進制數據。
(14)WebLogic:
WebLogic是美國Oracle公司出品的一個application server,確切的說是一個基於JAVAEE架構的中間件,WebLogic是用於開發、集成、部署和管理大型分佈式Web應用、網絡應用和數據庫應用的Java應用服務器。將Java的動態功能和Java Enterprise標準的安全性引入大型網絡應用的開發、集成、部署和管理之中。
(15)OSGi:
OSGi(Open Service Gateway Initiative)技術是面向Java的動態模型系統。OSGi服務平臺向Java提供服務,這些服務使Java成爲軟件集成和軟件開發的首選環境。Java提供在多個平臺支持產品的可移植性。OSGi技術提供容許應用程序使用精煉、可重用和可協做的組件構建的標準化原語。這些組件可以組裝進一個應用和部署中。