文档章节

commons-pool2学习与使用

39YX
 39YX
发布于 2017/05/03 11:16
字数 1247
阅读 242
收藏 0

 

工厂实现 

package pool;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;

public class MyKeyedPooledObjectFactory implements KeyedPooledObjectFactory<String, User> {
	
	private static final User USER = new User("aa",System.currentTimeMillis());
	
	private static final Map<String,User> USER_OBJECT = new ConcurrentHashMap<String, User>(); 

	public PooledObject<User> makeObject(String key) throws Exception {
		User user = null;
		if(USER_OBJECT.containsKey(key)){
			user = USER_OBJECT.get(key);
		}else{
			synchronized(USER_OBJECT){
				user = new User(key,System.currentTimeMillis());
				USER_OBJECT.put(key, user);
			}
		}
		//return new DefaultPooledObject<User>(new User(key,System.currentTimeMillis()));
		return new DefaultPooledObject<User>(user);
	}

	public void destroyObject(String key, PooledObject<User> p)
			throws Exception {
		print("destroyObject", p);
	}

	public boolean validateObject(String key, PooledObject<User> p) {
		print("validateObject", p);
		return true;
	}

	public void activateObject(String key, PooledObject<User> p)
			throws Exception {
		print("activateObject", p);
	}

	public void passivateObject(String key, PooledObject<User> p)
			throws Exception {
		print("passivateObject", p);
	}
	
	private void print(String str,PooledObject<User> p){
		DefaultPooledObject<User> pooled = (DefaultPooledObject<User>)p;
		System.out.println(str + " >> info : " + p + " getBorrowedCount : " + pooled.getBorrowedCount());
	}

}

 

package pool;

public class User {
	private String name;
	private long time;

	public User() {
		super();
	}

	public User(String name, long time) {
		super();
		this.name = name;
		this.time = time;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public long getTime() {
		return time;
	}

	public void setTime(long time) {
		this.time = time;
	}

	@Override
	public String toString() {
		return "User [name=" + name + ", time=" + time + "]";
	}
}

//EvictionPolicy 自定义清除策略类(定时作业用)

package pool;

import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.EvictionConfig;
import org.apache.commons.pool2.impl.EvictionPolicy;

public class MyEvictionPolicy implements EvictionPolicy<User> {
	public boolean evict(EvictionConfig config, PooledObject<User> underTest,
			int idleCount) {
		/**
		 * config : idleEvictTime 的值由setMinEvictableIdleTimeMillis设置  默认:1800000 
		 * 			idleSoftEvictTime setSoftMinEvictableIdleTimeMillis 默认:1800000 
		 * 			minIdle setMinIdlePerKey 如果MinIdlePerKey > MaxIdlePerKey 则取 MaxIdlePerKey 否则取 MinIdlePerKey
		 * 不设置也可以有默认值的 
		 */
		System.out.println("MyEvictionPolicy");
		//返回true代表要 清除
		return true;
	}

}

//测试代码

//参考资料

http://www.cnblogs.com/jinzhiming/p/5120623.html

http://www.open-open.com/lib/view/open1415453575730.html

package pool;

import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;

import org.apache.commons.pool2.KeyedObjectPool;
import org.apache.commons.pool2.KeyedPooledObjectFactory;
import org.apache.commons.pool2.PoolUtils;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.apache.commons.pool2.proxy.CglibProxySource;
import org.apache.commons.pool2.proxy.ProxiedKeyedObjectPool;

public class Test {
	private static final Object LOCK = new Object();
	public static void main(String[] args) throws InterruptedException {
		final KeyedObjectPool<String, User> pool = getGenericKeyedObjectPool();
		//final GenericKeyedObjectPool<String, User> pool = new GenericKeyedObjectPool<String, User>(factory, config);
		//addObject 相当于一种预加载  把预先创建好的对象放在pool里面 
		try {
			pool.addObject("aa");
			pool.addObject("aa");
			pool.addObject("aa");
			pool.addObject("aa");
			pool.addObject("aa");
			pool.addObject("aa");
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		
		//TimeUnit.SECONDS.sleep(2);
		//多线程测试
		/*for(int i = 0;i < 20;i++){
			new Thread(new Runnable() {
				public void run() {
					for(int j = 0;j < 20;j++){
						try {
							String key = "aa" + j;
							synchronized(LOCK){
								////////////////////////////////////////////////////////////
								//如果要调用returnObject方法 那么 borrowObject returnObject必需在一个同步块里(如果是多线程环境的话) 原因看下面returnObject注释
								User user = pool.borrowObject(key);
								//不能连续调用returnObject否则会抛异常 returnObject方法会非 PooledObjectState.ALLOCATED的对象变为PooledObjectState.RETURNING
								pool.returnObject(key, user);
								/////////////////////////////////////////////////////////////
								System.out.println(user);
							}
						} catch (NoSuchElementException e) {
							e.printStackTrace();
						} catch (IllegalStateException e) {
							e.printStackTrace();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}).start();
		}*/
		//单线程测试
		for(int i = 0;i < 20;i++){
			try {
				String key = "aa";
				User user = pool.borrowObject(key);
				//如果第一次从缓存里没取到那么再次获取 如果在 borrowMaxWaitMillis没有获取到则抛异常 前提 blockWhenExhausted设置为true
				//User user = pool.borrowObject(key,2);
				//if(i == 9){
				//	System.out.println();
				//}
				//不能连续调用returnObject否则会抛异常 returnObject方法会非 PooledObjectState.ALLOCATED的对象变为PooledObjectState.RETURNING
				pool.returnObject(key, user);
				//如果用了代理(ProxiedKeyedObjectPool)的话 那么 调用returnObject后 该值不可用 用的话 会报错的 因为returnObject 会把原始值赋空值
				System.out.println(user);
			} catch (NoSuchElementException e) {
				e.printStackTrace();
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		TimeUnit.MINUTES.sleep(10);
	}
	
	private static KeyedObjectPool<String, User> getProxiedKeyedObjectPool(){
		KeyedObjectPool<String, User> p = getGenericKeyedObjectPool();
		CglibProxySource<User> proxy = new CglibProxySource<User>(User.class);
		KeyedObjectPool<String, User> pool = new ProxiedKeyedObjectPool<String, User>(p,proxy);
		return pool;
	}
	
	private static KeyedObjectPool<String, User> getGenericKeyedObjectPool(){
		KeyedPooledObjectFactory<String, User> factory = new MyKeyedPooledObjectFactory();

		GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig();
		/**
		 * 如果pool里没有存储(如果要存储得调用returnObject才行因为borrowObject调用完后会调用deregister方法移除缓存) 
		 * 那么没辞都会从工厂里获取对象(对于pool来说就是创建) 这里指每个key最多能创建多少个对象 默认为8(当到达限制后线程会等待) 负数代表不限制
		 */
		config.setMaxTotalPerKey(-1);
		config.setMaxTotal(-1);//最多能存储多少个数据 负数代表不限制 默认-1
		config.setMaxWaitMillis(-1);//和borrowObject(key,2);第二个参数一个意义
		config.setFairness(false);//设置锁的模式  默认为非公平所
		//缓存里最多能存多少个数据和MaxTotal不同的是 MaxTotal是针对所有key 这个是针对单个key允许存多少个数据 如果设置为0的话addObject是没作用的哦
		config.setMaxTotalPerKey(8);
		//config.setLifo(true);//后进先出法 用于pool缓存
		//还是弄默认吧。。。。。。。。。在取的时候因为缓存中有数据所以没有创建 所以导致调用returnObject方法获取不到缓存而报错 //最好是CPU核数*2吧 好像都是这么玩的 比如netty
		config.setMaxIdlePerKey(8);//(该配置属于returnObject方法)如果maxIdlePerKey 大于预加载里的数量(同一个key) 那么预加载的作用失效(前提是你调用returnObject方法)
		config.setBlockWhenExhausted(true);//默认为TRUE 请看单线程测试用例
		//config.setTestOnReturn(true);//针对returnObject方法 默认为false 当设置为true时会调用工厂的validateObject方法 若验证失败则调用工厂方法的destroyObject方法
		//该参数大于0(默认-1) 启动清楚数据作业 该功能需要setEvictionPolicyClassName支持
		config.setTimeBetweenEvictionRunsMillis(1000 * 10);
		config.setTestWhileIdle(true);//(默认为false)代表如果evictionPolicyClassName验证失败 是否需要调用工厂的validateObject方法 如果返回false则清楚数据
		config.setEvictionPolicyClassName(MyEvictionPolicy.class.getName());//默认DefaultEvictionPolicy
		/**
		 * SynchronizedKeyedObjectPool所有方法都加了锁
		 */
		KeyedObjectPool<String, User> pool = new GenericKeyedObjectPool<String, User>(factory, config);
		return pool;
	}
}

 

© 著作权归作者所有

上一篇: maven插件
下一篇: maven插件
39YX
粉丝 0
博文 2
码字总数 1285
作品 0
黄浦
程序员
私信 提问
使用commons-pool2实现FTP连接池

一. 连接池概述 频繁的建立和关闭连接,会极大的降低系统的性能,而连接池会在初始化的时候会创建一定数量的连接,每次访问只需从连接池里获取连接,使用完毕后再放回连接池,并不是直接关闭连...

瞿落
2018/06/23
0
0
解决dbcp数据库连接池错误

使用dbcp数据库连接池时报错 java.lang.NoClassDefFoundError: org/apache/commons/pool2/PooledObjectFactory 原因:缺少commons-pool2-2.4.2.jar commons-dbcp2-2.1.1.jar 本文转自爱情897......

技术小胖子
2017/11/07
0
0
Apache Common-pool2对象池浅析

Apache Common-pool2包提供了一个通用的对象池技术的实现。可以很方便的基于它来实现自己的对象池,比如DBCP和Jedis他们的内部对象池的实现就是依赖于Common-pool2。 对象的创建和销毁在一定...

同明
2016/06/14
210
0
GenericObjectPool参数解析

序 本文主要解析一下apache common pools下的GenericObjectPool的参数设置 GenericObjectPool commons-pool2-2.4.2-sources.jar!/org/apache/commons/pool2/impl/GenericObjectPool.java 默认......

go4it
2017/10/18
0
0
聊聊GenericObjectPool的泄露检测

序 本文主要聊聊GenericObjectPool的abandon参数。主要用来做连接池的泄露检测用。 object的状态 commons-pool2-2.4.2-sources.jar!/org/apache/commons/pool2/PooledObjectState.java aband......

go4it
2017/10/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Kernel DMA

为什么会有DMA(直接内存访问)?我们知道通常情况下,内存数据跟外设之间的通信是通过cpu来传递的。cpu运行io指令将数据从内存拷贝到外设的io端口,或者从外设的io端口拷贝到内存。由于外设...

yepanl
今天
3
0
hive

一、hive的定义: Hive是一个SQL解析引擎,将SQL语句转译成MR Job,然后再在Hadoop平台上运行,达到快速开发的目的 Hive中的表是纯逻辑表,就只是表的定义,即表的元数据。本质就是Hadoop的目...

霉男纸
今天
3
0
二、Spring Cloud—Eureka(Greenwich.SR1)

注:本系列文章所用工具及版本如下:开发工具(IDEA 2018.3.5),Spring Boot(2.1.3.RELEASE),Spring Cloud(Greenwich.SR1),Maven(3.6.0),JDK(1.8) Eureka: Eureka是Netflix开发...

倪伟伟
昨天
8
0
eclipse常用插件

amaterasUML https://takezoe.github.io/amateras-update-site/ https://github.com/takezoe/amateras-modeler modelGoon https://www.cnblogs.com/aademeng/articles/6890266.html......

大头鬼_yc
昨天
4
0
centos7修改命令行或图形界面启动模式

1.systemctl get-default命令获取当前模式 2.systemctl set-default graphical.target 修改启动模式(修改为图形界面,要是修改为命令行就multi-user.target) 2.systemctl set-default multi-...

大圣39
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部