池化,卷積和池化

來源:互聯網
上載者:User

池化,卷積和池化
  對於那些建立耗時較長,或者資源佔用較多的對象,比如網路連接,線程之類的資源,通常使用池化來管理這些對象,從而達到提高效能的目的。比如資料庫連接池(c3p0, dbcp), java的線程池 ExecutorService.Apache Commons Pool提供一套池化規範介面,以及實現通用邏輯,我們只需要要實現其抽象出來的方法就可以。Commons Pool主要有以下幾個對象  PooledObject:這個就是前面所說需要池化的資源,被池化的對象可以抽離出共有屬性,如,建立時間,狀態,最近一次使用時間等  PooledObjectFactory: 對象工廠,負責對PooledOjbect的建立,狀態驗證,銷毀之類的工作  ObjectPool: 對象池,它是負責和對象使用者直接打交道的, 對使用者提供擷取對象,返還對象介面  英文不太好的同學可能被這幾個對象的命名搞暈,其實世間萬物的道理都是想通的。如果把圖書館的書比作PooledObject 的話,那麼圖書館就是ObjectPool,圖書館為了管理書,對書添加了入庫時間,書借存狀態等用於管理的屬性。圖書館(ObjectPool)對借書人提供借書,還書的服務(即介面)。而書(PooledObject )的印刷,品質檢驗,回收(有點不現實)等實實在在的工作還是得交給印刷廠(PooledObjectFactory )來做。其流程關係如下:  下面看看如何使用Commons Pool如何?自己的對象池。建立自己的對象池大致需要以下工作,  1. 首先你已經編寫好了你的資來源物件(這部分不屬於池化內容),之後編寫實現apache的PooledObjectFactory<T>介面的Factory類,這是編寫自己對象池最主要的工作。你的Factory可能需要添加一些用於池化對象的初始化 ,池化對象的驗證等參數作為成員變數。  2. 編寫自己的Pool類,讓其繼承或者內部引用apache的GenericObjectPool<T>,GenericObjectPool實現了ObjectPool介面,已經封裝了對池化對象的生命週期管理邏輯  3. 可選部分,繼承apache的GenericObjectPoolConfig,重寫構造器,添加一些適合自己業務情境的初始化參數。  我們以Jedis的源碼為例,學習它的實現。我們先看下使用JedisPool操作Redis的簡單例子

package com.eg.test.redis;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;public class TestPool {     public static void main(String[] args) {        //JedisPoolConfig繼承apache的GenericObjectPoolConfig,配置Pool的相關參數如下:        JedisPoolConfig config = new JedisPoolConfig();         //如果賦值為-1,則表示不限制;如果pool已經分配了maxActive個jedis執行個體,則此時pool的狀態為exhausted(耗盡)。         config.setMaxTotal(500);         //控制一個pool最多有多少個狀態為idle(閒置)的jedis執行個體。         config.setMaxIdle(5);         //表示當borrow(引入)一個jedis執行個體時,最大的等待時間,如果超過等待時間,則直接拋出JedisConnectionException;         config.setMaxWaitMillis(30000);;         //在borrow一個jedis執行個體時,是否提前進行validate操作;如果為true,則得到的jedis執行個體均是可用的;         config.setTestOnBorrow(true);                JedisPool pool = new JedisPool(config, "192.168.2.191", 8888);         //從pool中擷取對象        Jedis jedis = pool.getResource();         String value = jedis.get("someKey");            }}

  首先看JedisFactory的實現:

class JedisFactory implements PooledObjectFactory<Jedis> {     private final AtomicReference<HostAndPort> hostAndPort = new AtomicReference<HostAndPort>();     private final int connectionTimeout;     private final int soTimeout;     //省略建構函式,都是一些初始化成員變數的操作     @Override     public void activateObject(PooledObject<Jedis> pooledJedis) throws Exception {           final BinaryJedis jedis = pooledJedis.getObject();           if (jedis.getDB() != database) {                jedis.select(database);           }     }     @Override     public void destroyObject(PooledObject<Jedis> pooledJedis) throws Exception {           final BinaryJedis jedis = pooledJedis.getObject();           if (jedis.isConnected()) {                try {                     try {                           jedis.quit();                     } catch (Exception e) {                     }                     jedis.disconnect();                } catch (Exception e) {                }           }     }     @Override     public PooledObject<Jedis> makeObject() throws Exception {           final HostAndPort hostAndPort = this.hostAndPort.get();           final Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort(), connectionTimeout, soTimeout, ssl,                   sslSocketFactory, sslParameters, hostnameVerifier);           try {                jedis.connect();                if (null != this.password) {                     jedis.auth(this.password);                }                if (database != 0) {                     jedis.select(database);                }                if (clientName != null) {                     jedis.clientSetname(clientName);                }           } catch (JedisException je) {                jedis.close();                throw je;           }           return new DefaultPooledObject<Jedis>(jedis);     }     @Override     public void passivateObject(PooledObject<Jedis> pooledJedis) throws Exception {           // TODO maybe should select db 0? Not sure right now.     }     @Override     public boolean validateObject(PooledObject<Jedis> pooledJedis) {           final BinaryJedis jedis = pooledJedis.getObject();           try {                HostAndPort hostAndPort = this.hostAndPort.get();                String connectionHost = jedis.getClient().getHost();                int connectionPort = jedis.getClient().getPort();                return hostAndPort.getHost().equals(connectionHost) && hostAndPort.getPort() == connectionPort                        && jedis.isConnected() && jedis.ping().equals("PONG");           } catch (final Exception e) {                return false;           }     }}

  我們看到JedisFactory代碼較少,但是邏輯很清晰。該Factory將作為ObjectPool的成員變數,其中四個重寫的方法被ObjectPool管理對象生命週期的時候調用。makeobject()方法負責建立Jedis執行個體,成功調用connect()方法建立有狀態的socket串連之後,返回一個封裝了jedis的DefaultPooledObject對象,DefaultPooledObject實現了關於統計池化對象狀態資訊的PooledObject介面。validateObject()方法用於對對象狀態的檢驗,Jedis對象的狀態通過socket的ping-pong來驗證串連是否正常。destroyObject()方法用來銷毀對象,Jedis對象將會中斷連線,回收資源。

  再看JedisPool的實現,由於JedisPool繼承Pool<T>,所以我們主要看Pool<T>的部分代碼:

public abstract class Pool<T> implements Closeable {     protected GenericObjectPool<T> internalPool;     public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {           initPool(poolConfig, factory);     }     public boolean isClosed() {           return this.internalPool.isClosed();     }     public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) {           if (this.internalPool != null) {                try {                     closeInternalPool();                } catch (Exception e) {                }           }           this.internalPool = new GenericObjectPool<T>(factory, poolConfig);     }     public T getResource() {           try {                return internalPool.borrowObject();           } catch (NoSuchElementException nse) {                throw new JedisException("Could not get a resource from the pool", nse);           } catch (Exception e) {                throw new JedisConnectionException("Could not get a resource from the pool", e);           }     }     protected void returnResourceObject(final T resource) {           if (resource == null) {                return;           }           try {                internalPool.returnObject(resource);           } catch (Exception e) {                throw new JedisException("Could not return the resource to the pool", e);           }     }     public void addObjects(int count) {           try {                for (int i = 0; i < count; i++) {                     this.internalPool.addObject();                }           } catch (Exception e) {                throw new JedisException("Error trying to add idle objects", e);           }     }}
  JedisPool通過內部引用GenericObjectPool,封裝其介面的裝飾者模式,相比繼承來說這種模式更加靈活。JedisPool的構造方法需要將JedisFactory以及JedisPoolConfig建立標準的ObjectPool作為自己的成員變數。所以pool.getResource()方法的背後還是調用PoolObject.borrowObject()。   最後我們稍微看下JedisPoolConfig,只是做了一些預初始化參數的工作。
public class JedisPoolConfig extends GenericObjectPoolConfig {     public JedisPoolConfig() {           // defaults to make your life with connection pool easier :)           setTestWhileIdle(true);           setMinEvictableIdleTimeMillis(60000);           setTimeBetweenEvictionRunsMillis(30000);           setNumTestsPerEvictionRun(-1);     }}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.