通用池:commons pool 2

首先感谢下文作者,虽然没看你的内容,但是参考了参数。

Apache commons-pool对象池原理分析

最近遇到一个场景:

我作为一个中间件,连接一个没有提供接口的网站,htmlunit模拟html交互,然后把数据返回;对客户来说,我提供了一组标准接口。

因为该网站需要登录,网站登录过程很慢,所以面临两个问题:

第一是WebClient需要重用;

第二是不同的用户的htmlunit的WebClient实例是不能混用的,但是对于单用户来说,可能需要一个WebClient池。

本来想自己寨一个,后来想想细节太多不合适。先看了google guava cache,觉得api太复杂了,完全没看懂;然后又想到10年前看过apache commons pool源代码,查了一下现在是pool2了,完全重写,仔细看了看api,正好是我所需要的。

 

pool2实际使用很简单,但是官网的例子不太给力。其实只有三个要点(为什么是三点...):

1.Factory

回调。用于对象创建,销毁,验证,防止发呆等。

 

2.Pool的配置

池的参数。比如最大多少个,最小多少个,最长发呆时间(发呆过长就remove了),等等。

 

3.Pool实例

实际干活的。

 

针对我这个例子,首先定义一个factory

 

import com.gargoylesoftware.htmlunit.BrowserVersion
import com.gargoylesoftware.htmlunit.WebClient
import com.hitoz.auexpress.express.WebClientKey
import org.apache.commons.pool2.BaseKeyedPooledObjectFactory
import org.apache.commons.pool2.PooledObject
import org.apache.commons.pool2.impl.DefaultPooledObject

/**
 * Created by Ken on 2014/5/27.
 */
class WebClientFactory extends BaseKeyedPooledObjectFactory<WebClientKey, WebClient> {

    @Override
    void destroyObject(WebClientKey key, PooledObject<WebClient> p) throws Exception {
        key.worker?.doCleanup(p.object)
    }

    @Override
    public WebClient create(WebClientKey key) throws Exception {
        WebClient webClient = new WebClient(BrowserVersion.INTERNET_EXPLORER_8)
        webClient.options.activeXNative = false
        webClient.options.redirectEnabled = true
        webClient.options.useInsecureSSL = true
        webClient.options.javaScriptEnabled = false
        webClient.options.cssEnabled = false
        webClient.options.timeout = 10 * 1000L//10s
        webClient.options.throwExceptionOnFailingStatusCode = false

        key.worker?.doInit(key, webClient)
        return webClient
    }

    @Override
    public PooledObject<WebClient> wrap(WebClient value) {
        return new DefaultPooledObject<WebClient>(value)
    }

    @Override
    void passivateObject(WebClientKey key, PooledObject<WebClient> p) throws Exception {
        p.object?.closeAllWindows()
    }
}

 然后是参数:

 

 

 

GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig()
        config.setMaxTotal(500) //整个池最大值
        config.setMaxTotalPerKey(5) //每个key的最大
        config.setBlockWhenExhausted(true)
        config.setMinIdlePerKey(0)
        config.setMaxWaitMillis(-1) //获取不到永远等待
        config.setNumTestsPerEvictionRun(Integer.MAX_VALUE) // always test all idle objects
        config.setTestOnBorrow(true)
        config.setTestOnReturn(false)
        config.setTestWhileIdle(false)
        config.setTimeBetweenEvictionRunsMillis(1 * 60000L) //-1不启动。默认1min一次
        config.setMinEvictableIdleTimeMillis(10 * 60000L) //可发呆的时间,10mins
        config.setTestWhileIdle(false)  //发呆过长移除的时候是否test一下先

 

 

最后是干活的pool

 

WebClientFactory webClientFactory = new WebClientFactory()
GenericKeyedObjectPool<WebClientKey, WebClient> pool = new GenericKeyedObjectPool<WebClientKey, WebClient>(webClientFactory)

 

 

ok,从现在开始,只需要操作pool就可以了。

获取对象是

def webClient = pool.borrowObject(key)

使用完毕记得在finally里面

pool.returnObject(key, webClient)

 

通篇都是groovy代码,加上分号就是java。

 

 

你可能感兴趣的:(commons)