日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

享元模式源码解析(jdk+tomcat)

發布時間:2024/4/13 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 享元模式源码解析(jdk+tomcat) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
首先我們看一下Integer這個類,在使用它的時候非常非常的頻繁,那我們看一下Integer有一個方法,叫valueOfpublic final class Integer extends Number implements Comparable<Integer> public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i); }看一下里面的實現,首先做一個斷言的判斷,如果大于IntegerCache的最小值,并且小于等于IntegerCache的最大值,我們直接從Cache里面獲取,否則返回一個New出來的Integer對象,經常有一些Integer的判斷,通過Integer的各種構造,然后把構造出來的數字做等等判斷,讓你們判斷這個結果是true還是false,那這種題也是比較常見,這里面就要對IntegerCache了解,這段邏輯也非常清晰,也就是說如果走到return IntegerCache.cache[i + (-IntegerCache.low)];這里,這里并不是new出來的IntegerCache對象,所以數字沒有進入到if里面的時候,都是new出來的Integer對象,他們肯定不是同一個對象,所以這個數字如果不在這個范圍,==的時候一定是false,那很簡單我們來測試一下/*** Cache to support the object identity semantics of autoboxing for values between* -128 and 127 (inclusive) as required by JLS.** The cache is initialized on first usage. The size of the cache* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.* During VM initialization, java.lang.Integer.IntegerCache.high property* may be set and saved in the private system properties in the* sun.misc.VM class.*/private static class IntegerCache {static final int low = -128;static final int high;static final Integer cache[];static {// high value may be configured by propertyint h = 127;String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);// range [-128, 127] must be interned (JLS7 5.1.7)assert IntegerCache.high >= 127;}private IntegerCache() {} }IntegerCache這個類是一個private的靜態內部類,最小值是-128,而high在靜態塊里邊,聲明了為127,也就是說如果我們小于等于-128,大于等于127的話,不會在Cache里邊,而這個high的值也是可以修改的,String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");我們看一下這一行,這里面從JVM的參數里面獲取IntegerCache的最大值,然后再進行一些判斷,非常容易理解,然后同理Long類型里面也是有Cache的private static class LongCache {private LongCache(){}static final Long cache[] = new Long[-(-128) + 127 + 1];static {for(int i = 0; i < cache.length; i++)cache[i] = new Long(i - 128);} }這里面也是有LongCache,我們再看一下他的valueOf方法呢/*** Returns a {@code Long} instance representing the specified* {@code long} value.* If a new {@code Long} instance is not required, this method* should generally be used in preference to the constructor* {@link #Long(long)}, as this method is likely to yield* significantly better space and time performance by caching* frequently requested values.** Note that unlike the {@linkplain Integer#valueOf(int)* corresponding method} in the {@code Integer} class, this method* is <em>not</em> required to cache values within a particular* range.** @param l a long value.* @return a {@code Long} instance representing {@code l}.* @since 1.5*/ public static Long valueOf(long l) {final int offset = 128;if (l >= -128 && l <= 127) { // will cachereturn LongCache.cache[(int)l + offset];}return new Long(l); }他的邏輯是類似的,說完這些我們再看一個,Tomcat提供的common連接池,我們打開這個類,GenericObjectPool,這個很明顯就是一個連接池,我們先看一下GenericObjectPoolConfig,連接池里默認的一些配置,也就是說如果這些數字如果我們不配置的話,也會有,那他的實現很簡單,我們隨便找一個,GenericKeyedObjectPool,有兩個版本,一個是pool2,一個pool1,我們就看pool2的,那我們注意這個連接池,肯定有拿,肯定有放,我可以從這個連接池里界一個對象出來,借過來我使用,使用完之后我還要放回去,我們看一個方法,borrowObject,@Override public T borrowObject(final K key) throws Exception {return borrowObject(key, getMaxWaitMillis()); }這里面又調用這個borrowObject(key, getMaxWaitMillis())方法,我們看一下,我們往下看一下,public T borrowObject(final K key, final long borrowMaxWaitMillis) throws Exception {assertOpen();PooledObject<T> p = null;// Get local copy of current config so it is consistent for entire// method executionfinal boolean blockWhenExhausted = getBlockWhenExhausted();boolean create;final long waitTime = System.currentTimeMillis();final ObjectDeque<T> objectDeque = register(key);try {while (p == null) {create = false;p = objectDeque.getIdleObjects().pollFirst();if (p == null) {p = create(key);if (p != null) {create = true;}}if (blockWhenExhausted) {if (p == null) {if (borrowMaxWaitMillis < 0) {p = objectDeque.getIdleObjects().takeFirst();} else {p = objectDeque.getIdleObjects().pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS);}}if (p == null) {throw new NoSuchElementException("Timeout waiting for idle object");}} else {if (p == null) {throw new NoSuchElementException("Pool exhausted");}}if (!p.allocate()) {p = null;}if (p != null) {try {factory.activateObject(key, p);} catch (final Exception e) {try {destroy(key, p, true);} catch (final Exception e1) {// Ignore - activation failure is more important}p = null;if (create) {final NoSuchElementException nsee = new NoSuchElementException("Unable to activate object");nsee.initCause(e);throw nsee;}}if (p != null && (getTestOnBorrow() || create && getTestOnCreate())) {boolean validate = false;Throwable validationThrowable = null;try {validate = factory.validateObject(key, p);} catch (final Throwable t) {PoolUtils.checkRethrow(t);validationThrowable = t;}if (!validate) {try {destroy(key, p, true);destroyedByBorrowValidationCount.incrementAndGet();} catch (final Exception e) {// Ignore - validation failure is more important}p = null;if (create) {final NoSuchElementException nsee = new NoSuchElementException("Unable to validate object");nsee.initCause(validationThrowable);throw nsee;}}}}}} finally {deregister(key);}updateStatsBorrow(p, System.currentTimeMillis() - waitTime);return p.getObject();}這里面通過ObjectDeque對象,一個雙端隊列,讓他來保持對象池的對象,在最上面把這個連接池聲明為一個空,PooledObject<T> p = null;我們看一下下面怎么用,然后在try里面對他實際的使用,通過Object的雙端隊列,來保存連接對象,當然這里還會調用一些factory的,factory.activateObject(key, p);存活著的對象,factory里面有很多的方法,public interface KeyedPooledObjectFactory<K,V>,我們來看一下方法,有存活的對象activateObject,有銷毀的對象destroyObject,創建對象destroyObject,鈍化對象passivateObject,校驗對象validateObject,那很簡單,關注對象的幾個狀態,首先用這個池對象工廠來創建對象,那將不用的池對象進行鈍化,對要使用的對象進行激活,并且還要對池對象進行激活,把有問題的池對象進行銷毀,那我們先回來繼續來看,我們再來看一個方法returnObject,把一個對象返回回來,@Overridepublic void returnObject(final K key, final T obj) {final ObjectDeque<T> objectDeque = poolMap.get(key);final PooledObject<T> p = objectDeque.getAllObjects().get(new IdentityWrapper<>(obj));if (p == null) {throw new IllegalStateException("Returned object not currently part of this pool");}synchronized(p) {final PooledObjectState state = p.getState();if (state != PooledObjectState.ALLOCATED) {throw new IllegalStateException("Object has already been returned to this pool or is invalid");}p.markReturning(); // Keep from being marked abandoned (once GKOP does this)}final long activeTime = p.getActiveTimeMillis();try {if (getTestOnReturn()) {if (!factory.validateObject(key, p)) {try {destroy(key, p, true);} catch (final Exception e) {swallowException(e);}if (objectDeque.idleObjects.hasTakeWaiters()) {try {addObject(key);} catch (final Exception e) {swallowException(e);}}return;}}try {factory.passivateObject(key, p);} catch (final Exception e1) {swallowException(e1);try {destroy(key, p, true);} catch (final Exception e) {swallowException(e);}if (objectDeque.idleObjects.hasTakeWaiters()) {try {addObject(key);} catch (final Exception e) {swallowException(e);}}return;}if (!p.deallocate()) {throw new IllegalStateException("Object has already been returned to this pool");}final int maxIdle = getMaxIdlePerKey();final LinkedBlockingDeque<PooledObject<T>> idleObjects =objectDeque.getIdleObjects();if (isClosed() || maxIdle > -1 && maxIdle <= idleObjects.size()) {try {destroy(key, p, true);} catch (final Exception e) {swallowException(e);}} else {if (getLifo()) {idleObjects.addFirst(p);} else {idleObjects.addLast(p);}if (isClosed()) {// Pool closed while object was being added to idle objects.// Make sure the returned object is destroyed rather than left// in the idle object pool (which would effectively be a leak)clear(key);}}} finally {if (hasBorrowWaiters()) {reuseCapacity();}updateStatsReturn(activeTime);}}有一個poolMap,里面傳了一個key,打開看一下private final Map<K,ObjectDeque<T>> poolMap =new ConcurrentHashMap<>(); poolMap它是一個ConcurrentHashMap,也就是說他折中了HashMap和Hashtable,使用ConcurrentHashMap,來做這個連接池的Map,非常容易理解,也就是說在這個雙端隊列上一層,又包裝了一層Map,也就是說呢poolMap,是連接池的對象池,那這些都可以認為是享元模式的一個應用,非常容易理解,希望通過這個過程,對以后有類似的場景,我們就要考慮是否可以使用享元模式

?

總結

以上是生活随笔為你收集整理的享元模式源码解析(jdk+tomcat)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。