J2EE
Java Core Knowledge/Java Web Solution
摘要: 剛看到這個月的編程語言排行榜,很顯然java的霸主地位很快就會在發達國家被擠掉,C語言依然是王者(想想上個月自己買的兩個C語言的書,冷汗直流)。看來我遲早要回歸C,這才是真正的王道。
非常令人吃驚的是C++語言依然不夠堅挺,由于Windows 7/Windows 8的發力,C#很快就會搶占C++的市場,估計很快就會將C++從前三名中擠下去。
iPhone/iPad的熱銷讓Object C繼續火熱,前十的位置還是可以持續很久的,這一點毋庸置疑。移動設備開發的高端人才現在是高薪難求,如果有時間我也要繼續關注下。 閱讀全文
非常令人吃驚的是C++語言依然不夠堅挺,由于Windows 7/Windows 8的發力,C#很快就會搶占C++的市場,估計很快就會將C++從前三名中擠下去。
iPhone/iPad的熱銷讓Object C繼續火熱,前十的位置還是可以持續很久的,這一點毋庸置疑。移動設備開發的高端人才現在是高薪難求,如果有時間我也要繼續關注下。 閱讀全文
摘要: Zookeeper客戶端和服務端維持一個長連接,每隔10s向服務端發送一個心跳,服務端返回客戶端一個響應。這就是一個Session連接,擁有全局唯一的session id。Session連接通常是一直有效,如果因為網絡原因斷開了連接,客戶端會使用相同的session id進行重連。由于服務端保留了session的各種狀態,尤其是各種瞬時節點是否刪除依賴于session是否失效。
Session失效問題
通常客戶端主動關閉連接認為是一次session失效。另外也有可能因為其它未知原因,例如網絡超時導致的session失效問題。在服務端看來,無法區分session失效是何種情況,一次一旦發生session失效,一定時間后就會將session持有的所有watcher以及瞬時節點刪除。
而對于Zookeeper客戶端而言,一旦發生失效不知道是否該重連,這涉及到watcher和瞬時節點問題,因此Zookeeper客戶端認為,一旦發生了seesion失效,那么就認為客戶端死掉了。從而所有操作都不能夠進行。參考 How should I handle SESSION 閱讀全文
Session失效問題
通常客戶端主動關閉連接認為是一次session失效。另外也有可能因為其它未知原因,例如網絡超時導致的session失效問題。在服務端看來,無法區分session失效是何種情況,一次一旦發生session失效,一定時間后就會將session持有的所有watcher以及瞬時節點刪除。
而對于Zookeeper客戶端而言,一旦發生失效不知道是否該重連,這涉及到watcher和瞬時節點問題,因此Zookeeper客戶端認為,一旦發生了seesion失效,那么就認為客戶端死掉了。從而所有操作都不能夠進行。參考 How should I handle SESSION 閱讀全文
摘要: 當Ajax遇到GBK/GB2312,我們恨不能將所有項目的編碼統一改為UTF-8。顯然這個做法,成本太高了。下面給出了一個完善的解決方案。此方案不僅僅限于Ajax提交數據,也適用于普通訪問請求。 閱讀全文
摘要: 這一節中我們將詳細討論線程池是如何執行一個任務的,尤其是如何處理線程池的大小、核心大小、最大大小、任務隊列等之間的關系的。 閱讀全文
摘要: 本著開發的原則,既然用到了別人家的東西,所以決定公開出來,也算是給別人一個參考。 閱讀全文
摘要: Java里面線程池的頂級接口是Executor,但是嚴格意義上講Executor并不是一個線程池,而只是一個執行線程的工具。真正的線程池接口是ExecutorService。
下面這張圖完整描述了線程池的類體系結構。 閱讀全文
下面這張圖完整描述了線程池的類體系結構。 閱讀全文
摘要: 最近的項目使用的是舊的ibatis2.x版本,有時候為了方便調試,想輸出SQL執行的語句和參數。我記得應該有某些logger的日志級別修改為DEBUG就可以看到。當然為了方便可以直接在log4j(如果使用log4j的話)的root日志級別修改為DEBUG,并且輸出appender的接受級別修改為DEBUG就可以了。這樣是可以看到日志信息(SQL/參數)等,但是同時也輸出了過多的其它logger信息,顯然在一個稍微大一點的系統里面debug的信息應該都是非常多的,不說別的,光是spring的日志就夠好多頁了。
為了解決過多的日志,翻出ibatis源碼,看了下。ibatis的執行流程大致是這樣的。 閱讀全文
為了解決過多的日志,翻出ibatis源碼,看了下。ibatis的執行流程大致是這樣的。 閱讀全文
摘要:
這一節主要是談談讀寫鎖的實現。
上一節中提到,ReadWriteLock看起來有兩個鎖:readLock/writeLock。如果真的是兩個鎖的話,它們之間又是如何相互影響的呢?
事實上在ReentrantReadWriteLock里鎖的實現是靠java.util.concurrent.locks.ReentrantReadWriteLock.Sync完成的。這個類看起來比較眼熟,實際上它是AQS的一個子類,這中類似的結構在CountDownLatch、ReentrantLock、Semaphore里面都存在。同樣它也有兩種實現:公平鎖和非公平鎖,也就是java.util.concurrent.locks.ReentrantReadWriteLock.FairSync和java.util.concurrent.locks.ReentrantReadWriteLock.NonfairSync。這里暫且不提。
在ReentrantReadWriteLock里面的鎖主體就是一個Sync,也就是上面提到的FairSync或者NonfairSync,所以說實際 閱讀全文
這一節主要是談談讀寫鎖的實現。
上一節中提到,ReadWriteLock看起來有兩個鎖:readLock/writeLock。如果真的是兩個鎖的話,它們之間又是如何相互影響的呢?
事實上在ReentrantReadWriteLock里鎖的實現是靠java.util.concurrent.locks.ReentrantReadWriteLock.Sync完成的。這個類看起來比較眼熟,實際上它是AQS的一個子類,這中類似的結構在CountDownLatch、ReentrantLock、Semaphore里面都存在。同樣它也有兩種實現:公平鎖和非公平鎖,也就是java.util.concurrent.locks.ReentrantReadWriteLock.FairSync和java.util.concurrent.locks.ReentrantReadWriteLock.NonfairSync。這里暫且不提。
在ReentrantReadWriteLock里面的鎖主體就是一個Sync,也就是上面提到的FairSync或者NonfairSync,所以說實際 閱讀全文
摘要: 從這一節開始介紹鎖里面的最后一個工具:讀寫鎖(ReadWriteLock)。
ReentrantLock 實現了標準的互斥操作,也就是一次只能有一個線程持有鎖,也即所謂獨占鎖的概念。前面的章節中一直在強調這個特點。顯然這個特點在一定程度上面減低了吞吐量,實際上獨占鎖是一種保守的鎖策略,在這種情況下任何“讀/讀”,“寫/讀”,“寫/寫”操作都不能同時發生。但是同樣需要強調的一個概念是,鎖是有一定的開銷的,當并發比較大的時候,鎖的開銷就比較客觀了。所以如果可能的話就盡量少用鎖,非要用鎖的話就嘗試看能否改造為讀寫鎖。
ReadWriteLock描述的是:一個資源能夠被多個讀線程訪問,或者被一個寫線程訪問,但是不能同時存在讀寫線程。也就是說讀寫鎖使用的場合是一個共享資源被大量讀取操作,而只有少量的寫操作(修改數據)。清單1描述了ReadWriteLock的API。 閱讀全文
ReentrantLock 實現了標準的互斥操作,也就是一次只能有一個線程持有鎖,也即所謂獨占鎖的概念。前面的章節中一直在強調這個特點。顯然這個特點在一定程度上面減低了吞吐量,實際上獨占鎖是一種保守的鎖策略,在這種情況下任何“讀/讀”,“寫/讀”,“寫/寫”操作都不能同時發生。但是同樣需要強調的一個概念是,鎖是有一定的開銷的,當并發比較大的時候,鎖的開銷就比較客觀了。所以如果可能的話就盡量少用鎖,非要用鎖的話就嘗試看能否改造為讀寫鎖。
ReadWriteLock描述的是:一個資源能夠被多個讀線程訪問,或者被一個寫線程訪問,但是不能同時存在讀寫線程。也就是說讀寫鎖使用的場合是一個共享資源被大量讀取操作,而只有少量的寫操作(修改數據)。清單1描述了ReadWriteLock的API。 閱讀全文
摘要: Semaphore 是一個計數信號量。從概念上講,信號量維護了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然后再獲取該許可。每個 release() 添加一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實際的許可對象,Semaphore 只對可用許可的號碼進行計數,并采取相應的行動。
說白了,Semaphore是一個計數器,在計數器不為0的時候對線程就放行,一旦達到0,那么所有請求資源的新線程都會被阻塞,包括增加請求到許可的線程,也就是說Semaphore不是可重入的。每一次請求一個許可都會導致計數器減少1,同樣每次釋放一個許可都會導致計數器增加1,一旦達到了0,新的許可請求線程將被掛起。
緩存池整好使用此思想來實現的,比如鏈接池、對象池等。 閱讀全文
說白了,Semaphore是一個計數器,在計數器不為0的時候對線程就放行,一旦達到0,那么所有請求資源的新線程都會被阻塞,包括增加請求到許可的線程,也就是說Semaphore不是可重入的。每一次請求一個許可都會導致計數器減少1,同樣每次釋放一個許可都會導致計數器增加1,一旦達到了0,新的許可請求線程將被掛起。
緩存池整好使用此思想來實現的,比如鏈接池、對象池等。 閱讀全文
摘要:
如果說CountDownLatch是一次性的,那么CyclicBarrier正好可以循環使用。它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。所謂屏障點就是一組任務執行完畢的時刻。
閱讀全文
如果說CountDownLatch是一次性的,那么CyclicBarrier正好可以循環使用。它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。所謂屏障點就是一組任務執行完畢的時刻。
閱讀全文
摘要: 此小節介紹幾個與鎖有關的有用工具。
閉鎖(Latch)
閉鎖(Latch):一種同步方法,可以延遲線程的進度直到線程到達某個終點狀態。通俗的講就是,一個閉鎖相當于一扇大門,在大門打開之前所有線程都被阻斷,一旦大門打開所有線程都將通過,但是一旦大門打開,所有線程都通過了,那么這個閉鎖的狀態就失效了,門的狀態也就不能變了,只能是打開狀態。也就是說閉鎖的狀態是一次性的,它確保在閉鎖打開之前所有特定的活動都需要在閉鎖打開之后才能完成。
CountDownLatch是JDK 5+里面閉鎖的一個實現,允許一個或者多個線程等待某個事件的發生。CountDownLatch有一個正數計數器,countDown方法對計數器做減操作,await方法等待計數器達到0。所有await的線程都會阻塞直到計數器為0或者等待線程中斷或者超時。 閱讀全文
閉鎖(Latch)
閉鎖(Latch):一種同步方法,可以延遲線程的進度直到線程到達某個終點狀態。通俗的講就是,一個閉鎖相當于一扇大門,在大門打開之前所有線程都被阻斷,一旦大門打開所有線程都將通過,但是一旦大門打開,所有線程都通過了,那么這個閉鎖的狀態就失效了,門的狀態也就不能變了,只能是打開狀態。也就是說閉鎖的狀態是一次性的,它確保在閉鎖打開之前所有特定的活動都需要在閉鎖打開之后才能完成。
CountDownLatch是JDK 5+里面閉鎖的一個實現,允許一個或者多個線程等待某個事件的發生。CountDownLatch有一個正數計數器,countDown方法對計數器做減操作,await方法等待計數器達到0。所有await的線程都會阻塞直到計數器為0或者等待線程中斷或者超時。 閱讀全文
摘要: 接上篇,這篇從Lock.lock/unlock開始。特別說明在沒有特殊情況下所有程序、API、文檔都是基于JDK 6.0的。
在沒有深入了解內部機制及實現之前,先了解下為什么會存在公平鎖和非公平鎖。公平鎖保證一個阻塞的線程最終能夠獲得鎖,因為是有序的,所以總是可以按照請求的順序獲得鎖。不公平鎖意味著后請求鎖的線程可能在其前面排列的休眠線程恢復前拿到鎖,這樣就有可能提高并發的性能。這是因為通常情況下掛起的線程重新開始與它真正開始運行,二者之間會產生嚴重的延時。因此非公平鎖就可以利用這段時間完成操作。這是非公平鎖在某些時候比公平鎖性能要好的原因之一。 閱讀全文
在沒有深入了解內部機制及實現之前,先了解下為什么會存在公平鎖和非公平鎖。公平鎖保證一個阻塞的線程最終能夠獲得鎖,因為是有序的,所以總是可以按照請求的順序獲得鎖。不公平鎖意味著后請求鎖的線程可能在其前面排列的休眠線程恢復前拿到鎖,這樣就有可能提高并發的性能。這是因為通常情況下掛起的線程重新開始與它真正開始運行,二者之間會產生嚴重的延時。因此非公平鎖就可以利用這段時間完成操作。這是非公平鎖在某些時候比公平鎖性能要好的原因之一。 閱讀全文
摘要: 在理解J.U.C原理以及鎖機制之前,我們來介紹J.U.C框架最核心也是最復雜的一個基礎類:java.util.concurrent.locks.AbstractQueuedSynchronizer。
AQS
AbstractQueuedSynchronizer,簡稱AQS,是J.U.C最復雜的一個類,導致絕大多數講解并發原理或者實戰的時候都不會提到此類。但是虛心的作者愿意借助自己有限的能力和精力來探討一二(參考資源中也有一些作者做了部分的分析。)。
首先從理論知識開始,在了解了相關原理后會針對源碼進行一些分析,最后加上一些實戰來描述。 閱讀全文
AQS
AbstractQueuedSynchronizer,簡稱AQS,是J.U.C最復雜的一個類,導致絕大多數講解并發原理或者實戰的時候都不會提到此類。但是虛心的作者愿意借助自己有限的能力和精力來探討一二(參考資源中也有一些作者做了部分的分析。)。
首先從理論知識開始,在了解了相關原理后會針對源碼進行一些分析,最后加上一些實戰來描述。 閱讀全文
摘要: 前面的章節主要談談原子操作,至于與原子操作一些相關的問題或者說陷阱就放到最后的總結篇來整體說明。從這一章開始花少量的篇幅談談鎖機制。
上一個章節中談到了鎖機制,并且針對于原子操作談了一些相關的概念和設計思想。接下來的文章中,盡可能的深入研究鎖機制,并且理解里面的原理和實際應用場合。
盡管synchronized在語法上已經足夠簡單了,在JDK 5之前只能借助此實現,但是由于是獨占鎖,性能卻不高,因此JDK 5以后就開始借助于JNI來完成更高級的鎖實現。
JDK 5中的鎖是接口java.util.concurrent.locks.Lock。另外java.util.concurrent.locks.ReadWriteLock提供了一對可供讀寫并發的鎖。根據前面的規則,我們從java.util.concurrent.locks.Lock的API開始。 閱讀全文
上一個章節中談到了鎖機制,并且針對于原子操作談了一些相關的概念和設計思想。接下來的文章中,盡可能的深入研究鎖機制,并且理解里面的原理和實際應用場合。
盡管synchronized在語法上已經足夠簡單了,在JDK 5之前只能借助此實現,但是由于是獨占鎖,性能卻不高,因此JDK 5以后就開始借助于JNI來完成更高級的鎖實現。
JDK 5中的鎖是接口java.util.concurrent.locks.Lock。另外java.util.concurrent.locks.ReadWriteLock提供了一對可供讀寫并發的鎖。根據前面的規則,我們從java.util.concurrent.locks.Lock的API開始。 閱讀全文
摘要: 在JDK 5之前Java語言是靠synchronized關鍵字保證同步的,這會導致有鎖(后面的章節還會談到鎖)。
鎖機制存在以下問題:
(1)在多線程競爭下,加鎖、釋放鎖會導致比較多的上下文切換和調度延時,引起性能問題。
(2)一個線程持有鎖會導致其它所有需要此鎖的線程掛起。
(3)如果一個優先級高的線程等待一個優先級低的線程釋放鎖會導致優先級倒置,引起性能風險。
volatile是不錯的機制,但是volatile不能保證原子性。因此對于同步最終還是要回到鎖機制上來。
獨占鎖是一種悲觀鎖,synchronized就是一種獨占鎖,會導致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖。而另一個更加有效的鎖就是樂觀鎖。所謂樂觀鎖就是,每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。 閱讀全文
鎖機制存在以下問題:
(1)在多線程競爭下,加鎖、釋放鎖會導致比較多的上下文切換和調度延時,引起性能問題。
(2)一個線程持有鎖會導致其它所有需要此鎖的線程掛起。
(3)如果一個優先級高的線程等待一個優先級低的線程釋放鎖會導致優先級倒置,引起性能風險。
volatile是不錯的機制,但是volatile不能保證原子性。因此對于同步最終還是要回到鎖機制上來。
獨占鎖是一種悲觀鎖,synchronized就是一種獨占鎖,會導致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖。而另一個更加有效的鎖就是樂觀鎖。所謂樂觀鎖就是,每次不加鎖而是假設沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。 閱讀全文
摘要: 在這個小結里面重點討論原子操作的原理和設計思想。
由于在下一個章節中會談到鎖機制,因此此小節中會適當引入鎖的概念。
在Java Concurrency in Practice中是這樣定義線程安全的:
當多個線程訪問一個類時,如果不用考慮這些線程在運行時環境下的調度和交替運行,并且不需要額外的同步及在調用方代碼不必做其他的協調,這個類的行為仍然是正確的,那么這個類就是線程安全的。 閱讀全文
由于在下一個章節中會談到鎖機制,因此此小節中會適當引入鎖的概念。
在Java Concurrency in Practice中是這樣定義線程安全的:
當多個線程訪問一個類時,如果不用考慮這些線程在運行時環境下的調度和交替運行,并且不需要額外的同步及在調用方代碼不必做其他的協調,這個類的行為仍然是正確的,那么這個類就是線程安全的。 閱讀全文
摘要: 在這一部分開始討論數組原子操作和一些其他的原子操作。
AtomicIntegerArray/AtomicLongArray/AtomicReferenceArray的API類似,選擇有代表性的AtomicIntegerArray來描述這些問題。
int get(int i)
獲取位置 i 的當前值。很顯然,由于這個是數組操作,就有索引越界的問題(IndexOutOfBoundsException異常)。
對于下面的API起始和AtomicInteger是類似的,這種通過方法、參數的名稱就能夠得到函數意義的寫法是非常值得稱贊的。在《重構:改善既有代碼的設計》和《代碼整潔之道》中都非常推崇這種做法。 閱讀全文
AtomicIntegerArray/AtomicLongArray/AtomicReferenceArray的API類似,選擇有代表性的AtomicIntegerArray來描述這些問題。
int get(int i)
獲取位置 i 的當前值。很顯然,由于這個是數組操作,就有索引越界的問題(IndexOutOfBoundsException異常)。
對于下面的API起始和AtomicInteger是類似的,這種通過方法、參數的名稱就能夠得到函數意義的寫法是非常值得稱贊的。在《重構:改善既有代碼的設計》和《代碼整潔之道》中都非常推崇這種做法。 閱讀全文
摘要: 從相對簡單的Atomic入手(java.util.concurrent是基于Queue的并發包,而Queue,很多情況下使用到了Atomic操作,因此首先從這里開始)。很多情況下我們只是需要一個簡單的、高效的、線程安全的遞增遞減方案。注意,這里有三個條件:簡單,意味著程序員盡可能少的操作底層或者實現起來要比較容易;高效意味著耗用資源要少,程序處理速度要快;線程安全也非常重要,這個在多線程下能保證數據的正確性。這三個條件看起來比較簡單,但是實現起來卻難以令人滿意。
通常情況下,在Java里面,++i或者--i不是線程安全的,這里面有三個獨立的操作:或者變量當前值,為該值+1/-1,然后寫回新的值。在沒有額外資源可以利用的情況下,只能使用加鎖才能保證讀-改-寫這三個操作時“原子性”的。 閱讀全文
通常情況下,在Java里面,++i或者--i不是線程安全的,這里面有三個獨立的操作:或者變量當前值,為該值+1/-1,然后寫回新的值。在沒有額外資源可以利用的情況下,只能使用加鎖才能保證讀-改-寫這三個操作時“原子性”的。 閱讀全文
摘要: 去年年底有一個Guice的研究計劃,可惜由于工作“繁忙”加上實際工作中沒有用上導致“無疾而終”,最終只是完成了Guice的初步學習教程,深入的研究沒有繼續進行下去。
最近一直用的比較多的就是java.util.concurrent(J.U.C),實際上這塊一直也沒有完全深入研究,這次準備花點時間研究下Java里面整個并發體系。初步的設想包括比較大的方便(包括硬件、軟件、思想以及誤區等等),因此可能會持續較長的時間。這塊內容也是Java在多線程方面引以為豪的一部分,深入這一部分不僅對整個Java體系有更深的了解,也對工作、學習的態度有多幫助。 閱讀全文
最近一直用的比較多的就是java.util.concurrent(J.U.C),實際上這塊一直也沒有完全深入研究,這次準備花點時間研究下Java里面整個并發體系。初步的設想包括比較大的方便(包括硬件、軟件、思想以及誤區等等),因此可能會持續較長的時間。這塊內容也是Java在多線程方面引以為豪的一部分,深入這一部分不僅對整個Java體系有更深的了解,也對工作、學習的態度有多幫助。 閱讀全文
摘要: 以前有段時間需要知道某些類在什么jar包中,這樣當出現ClassNotFoundException或者NoClassDefFoundError的時候我們就可以去找這個類在什么jar包中然后去引用此jar包即可。在我們的系統很小的時候我恨不能都將jar包放入eclipse中,這樣借助 eclipse平臺查找類就非常方便了。包括非常有用的Ctrl+Shift+T,Ctrl+T,Reference search等等,但是當工程多了大了的時候,上百個jar包放入eclipse中那個速度完全不是我能忍受的,稍微動一下就看到CPU一直在那抖動。好吧,用maven,更慢,簡直受不了,所以大多數時候Maven是一個比較好的批處理工具,和UI結合起來還不是很好用。
我發現我非常需要這個從jar包中尋找類的功能,我只需要看看我的類在什么地方而已,僅次而已!于是自己就寫了一個類查找器。非常簡單就是遍歷所有的jar包中的類,當匹配類名稱的時候就顯示類所在的jar包。
有以下幾個特性:
* 允許添加jar包,zip包
* 允許匹 閱讀全文
我發現我非常需要這個從jar包中尋找類的功能,我只需要看看我的類在什么地方而已,僅次而已!于是自己就寫了一個類查找器。非常簡單就是遍歷所有的jar包中的類,當匹配類名稱的時候就顯示類所在的jar包。
有以下幾個特性:
* 允許添加jar包,zip包
* 允許匹 閱讀全文
摘要: 本章節繼續討論Google Guice與第三方的整合,這里主要討論如何整合JMX的服務,通過guice-jmx插件我們可以很方便的將我們的服務注入到JMX服務中,這樣就能夠通過遠程調用來控制我們的服務。 閱讀全文
摘要: Google Guice 整合第三方組件。
在《Google Guice 入門教程06 – Web 和Servlet》 中我們看到了Guice 整合Struts 2的應用。本章節繼續討論Guice整合其它第三方組件的應用。
本章節重點談Guice與DWR和Spring的整合。
閱讀全文
在《Google Guice 入門教程06 – Web 和Servlet》 中我們看到了Guice 整合Struts 2的應用。本章節繼續討論Guice整合其它第三方組件的應用。
本章節重點談Guice與DWR和Spring的整合。
閱讀全文
摘要: 本章節主要講Guice中如何開發Servlet,當然了作為IOC的容器,Guice在這方面仍然局限于依賴注入功能。作為WEB方面的開發就不能不提Struts,這里著重談如何與Struts 2進行整合。 閱讀全文
摘要: 本章節主要討論Guice中AOP的使用,其中花了一些篇幅談AOP的概念,然后通過一些API和例子來說明AOP的具體使用過程。 閱讀全文
摘要: 本章節繼續討論依賴注入的其他話題,包括作用域(scope,這里有一個與線程綁定的作用域例子)、立即初始化(Eagerly Loading Bindings)、運行階段(Stage)、選項注入(Optional Injection)等等。 閱讀全文
摘要: 在我們64位的CenterOS上,指定了JVM的最大堆內存為5500M,但是在top和進程status中可以看到實際占用內存已經遠遠大于5500M,那么JVM到底占用多大內存?如果做到控制JVM的占用內存大小? 閱讀全文
摘要: 基于Google Guice 2.0的入門教程,本章節主要講類的依賴注入,也就是IOC容器的核心組件。 閱讀全文
摘要: 本文將探討單例模式的各種情況,并給出相應的建議。
單例模式應該是設計模式中比較簡單的一個,但是在多線程并發的環境下使用卻是不那么簡單了。
本文將探討在多線程下靜態域單例模式、雙重檢查鎖機制、類延時加載、同步鎖等機制的相關技術問題。 閱讀全文
單例模式應該是設計模式中比較簡單的一個,但是在多線程并發的環境下使用卻是不那么簡單了。
本文將探討在多線程下靜態域單例模式、雙重檢查鎖機制、類延時加載、同步鎖等機制的相關技術問題。 閱讀全文
摘要: 大家都知道HashMap不是線程安全的,但是大家的理解可能都不是十分準確。很顯然讀寫同一個key會導致不一致大家都能理解,但是如果讀寫一個總是存在HashMap中且不變的對象會有問題么?我們來試試看。 閱讀全文