java对象池化

对象池化技术 
 对象池化的基本思路是:将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度上减少频繁创建对象所造成的开销。用于充当保存对象的“容器”的对象,被称为“对象池”(Object Pool,或简称Pool)。


 对于没有状态的对象(例如String),在重复使用之前,无需进行任何处理;对于有状态的对象(例如StringBuffer),在重复使用之前,就需要把它们恢复到等同于刚刚生成时的状态。由于条件的限制,恢复某个对象的状态的操作不可能实现了的话,就得把这个对象抛弃,改用新创建的实例了。


 并非所有对象都适合拿来池化——因为维护对象池也要造成一定开销。对生成时开销不大的对象进行池化,反而可能会出现“维护对象池的开销”大于“生成新对象的开销”,从而使性能降低的情况。但是对于生成时开销可观的对象,池化技术就是提高性能的有效策略了。




什么时候不要池化 
  采用对象池化的本意,是要通过减少对象生成的次数,减少花在对象初始化上面的开销,从而提高整体的性能。然而池化处理本身也要付出代价,因此,并非任何情况下都适合采用对象池化。




 对于类似Point这样的轻量级对象,进行池化处理后,性能反而下降,因此不宜池化;  


  对于类似Hashtable这样的中量级对象,进行池化处理后,性能基本不变,一般不必池化(池化会使代码变复杂,增大维护的难度);


   对于类似JPanel这样的重量级对象,进行池化处理后,性能有所上升,可以考虑池化。


   根据使用方法的不同,实际的情况可能与这一测量结果略有出入。在配置较高的机器和技术较强的虚拟机上,不宜池化的对象的范围可能会更大。不过,对于像网络和数据库连接这类重量级的对象来说,目前还是有池化的必要。


  基本上,只在重复生成某种对象的操作成为影响性能的关键因素的时候,才适合进行对象池化。如果进行池化所能带来的性能提高并不重要的话,还是不采用对象池化技术,以保持代码的简明,而使用更好的硬件和更棒的虚拟机来提高性能为佳。



在Java中可以自定义或者借用第三方类库(如:apache commons-pool)实现对象池

以下是我自己实现的对象池,相当粗糙

思路是:

线程池中有两个集合,一个集合A存放空闲中的对象,一个集合B存放使用中的对象,

线程从A中拿到对象使用,并放入B中,当线程使用完对象之后从B中取出放回A中,

有状态的对象在使用之前先恢复为初始化状态,

当线程池中所有的对象都是使用中时(即都属于集合B),线程等待,当有线程返还对象时,线程唤醒。

001 package common.pool;
002  
003 import java.lang.reflect.Field;
004 import java.util.Collections;
005 import java.util.HashSet;
006 import java.util.Iterator;
007 import java.util.Set;
008  
009 /**
010  *
011  * @author JiaZhiTang
012  *自定义对象池
013  */
014 @SuppressWarnings({"unchecked","hiding"})
015 public class DIYObjectPool<E> {
016     private  Set<Object> activeSet = Collections.synchronizedSet(newHashSet<Object>());//正在被使用的对象的集合,已被同步
017     private  Set<Object> idleSet = Collections.synchronizedSet(newHashSet<Object>());//空闲的对象的集合,已被同步
018      
019     private Integer maxObjetc = 100;//最大对象数,默认值100
020     private Class<E> cls;//对象池 的类,因为java不能 直接使用泛型创建对象   T t = new T();
021     private Object lock = new Object();//线程等待监视器
022  
023  
024     /**
025      * 构造方法
026      * @param maxObjetc
027      * @param cls
028      */
029     public DIYObjectPool(Integer maxObjetc, Class<E> cls) {
030         this.maxObjetc = maxObjetc;
031         this.cls = cls;
032     }
033  
034     /**
035      * 从线程池中取出对象
036      * @param <E>
037      * @return
038      * @throws Exception
039      */
040     public synchronized <E> E borrowObject() throws Exception{
041         Object obj = null;
042         if(idleSet.size()>0){
043             Iterator<Object> iterator = idleSet.iterator();
044             obj = iterator.next();
045         }
046         if(obj != null){
047             idleSet.remove(obj);
048             activeSet.add(obj);
049         }else{
050             int size = activeSet.size()+idleSet.size();
051             if(size>=maxObjetc){
052                 synchronized (lock) {
053                     System.out.println("-----池中无对象,线程等待-----");
054                     lock.wait();
055                 }
056                 return borrowObject();
057             }else{
058                 obj = cls.newInstance();
059                 activeSet.add(obj);
060             }
061         }
062          
063         System.out.println("池中总对象数: "+(activeSet.size()+idleSet.size())+" ,使用中:"+activeSet.size()+" ,空闲中:"+idleSet.size());
064          
065         clearObject(obj);//有状态对象恢复默认初始化
066         return (E)obj;
067     }
068      
069     /**
070      * 对象使用完毕,返还线程池
071      * @param obj
072      */
073     public void returnObject(Object obj){
074         if(obj != null){
075             activeSet.remove(obj);
076             idleSet.add(obj);
077             synchronized (lock) {
078                 System.out.println("唤醒等待线程");
079                 lock.notify();
080 //              lock.notifyAll();
081             }
082              
083         }
084     }
085  
086  
087     /**
088      * 有状态对象恢复默认初始化
089      * @param obj
090      */
091     public void clearObject(Object obj) throws Exception{
092         Class<?> cls = obj.getClass();
093         Field[] fields = cls.getDeclaredFields();
094         for (Field field : fields) {
095             field.setAccessible(true);
096             field.set(obj, null);
097         }
098     }
099  
100  
101     public static void main(String[] args) throws Exception {
102         //初始化线程池
103         int max = 1000;
104         DIYObjectPool<Object> pool = new DIYObjectPool<Object>(max,Object.class);
105          
106         //自定义运行线程
107         class TestThread extends Thread{
108             DIYObjectPool objectPool;
109  
110             public TestThread(DIYObjectPool objectPool) {
111                 this.objectPool = objectPool;
112             }
113              
114             @Override
115             public void run() {
116                 try {
117                     Object obj = objectPool.borrowObject();
118                     Thread.sleep(3000);//假设对象被一个线程使用的3秒钟
119                     objectPool.returnObject(obj);
120                 catch (Exception e) {
121                     e.printStackTrace();
122                 }
123             }
124         }
125          
126         //并发max*2个线程
127         max = max*2;
128         for (int i = 0; i < max; i++) {
129             new TestThread(pool).start();
130         }
131     }
132      
133 }


不过实际开发中还是借用第三方类库来得好,毕竟自己水平有限     (╯﹏╰)

工厂类

01 package common.pool;
02  
03 import org.apache.commons.pool.PoolableObjectFactory;
04  
05 @SuppressWarnings({"unchecked"})
06 public class ObjectPoolFactory implements PoolableObjectFactory {
07  
08     private Class cls;
09     private static final String INIT_METHOD = "clearObject";//有状态对象恢复初始化的方法
10      
11      
12     public ObjectPoolFactory(Class cls) {
13         this.cls = cls;
14     }
15  
16     public void activateObject(Object arg0) throws Exception {
17         System.out.println("有状态对象恢复初始化");
18         try {
19             cls.getDeclaredMethod(INIT_METHOD).invoke(arg0);//有状态对象恢复初始化
20         catch (Exception e) {
21         }
22     }
23  
24     public void destroyObject(Object arg0) throws Exception {
25          
26     }
27  
28     public Object makeObject() throws Exception {
29         System.out.println("创建新对象");
30         return cls.newInstance();//创建新对象
31     }
32  
33     public void passivateObject(Object arg0) throws Exception {
34          
35     }
36  
37     public boolean validateObject(Object arg0) {
38         return false;
39     }
40  
41 }

对象池

01 package common.pool;
02  
03 import org.apache.commons.pool.impl.GenericObjectPool;
04  
05  
06 @SuppressWarnings({"unchecked"})
07 public class ObjectPool {
08      
09     private GenericObjectPool pool;
10      
11     public ObjectPool(Class cls) {
12         this.pool = new GenericObjectPool(new ObjectPoolFactory(cls));
13         pool.setMaxActive(2);//最大活动对象
14         pool.setMaxIdle(1);//最大空闲对象
15         pool.setMaxWait(100000);//最大等待时间
16     }
17      
18     /**
19      * 池中取出对象
20      * @param <T>
21      * @return
22      */
23     public <T> T borrowObject(){
24         T obj = null;
25         try {
26             obj = (T)pool.borrowObject();
27             System.out.println("获得对象");
28         catch (Exception e) {
29             System.out.println(e);
30         }
31         return obj;
32     }
33      
34     /**
35      * 对象放回池中
36      * @param obj
37      */
38     public void returnObject(Object obj){
39         try {
40             pool.returnObject(obj);
41             System.out.println("返还对象");
42         catch (Exception e) {
43             System.out.println(e);
44         }
45     }
46      
47 }

测试

01 package common.pool;
02  
03 public class Test {
04      
05     public static ObjectPool pool = new ObjectPool(Object.class);
06  
07     public static void main(String[] args) {
08         for (int i = 0; i < 2000; i++) {
09             new Thread(){
10                 public void run() {
11                     Object obj = Test.pool.borrowObject();
12                     System.out.println(obj.toString());
13                     try {
14                         Thread.sleep(1000);
15                     catch (Exception e) {
16                     }
17                     Test.pool.returnObject(obj);
18                 };
19             }.start();
20         }
21     }
22  
23 }

这里依赖于  commons-pool-1.5.6.jar

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
ElasticsearchClient是一种技术,通过创建一个对象池来管理Elasticsearch TransportClient对象的复用。在这个例子中,使用的是common pool池技术。具体实现是通过预加载client对象,使用时从池中获取对象,使用完毕后再将对象归还给池。这样可以避免频繁地创建和销毁大对象,提高client的利用率。 池ElasticsearchClient的基本使用方式如下: 1. 创建一个对象池配置类,可以自定义配置,或者使用默认配置。其中需要设置池中最大允许存储的client对象数量。 2. 创建一个要池的对象的工厂类,用于创建和销毁client对象。 3. 利用对象工厂类和配置类生成对象池。 4. 从池中获取一个client对象,使用完毕后归还给池。 以下是一个示例代码: ``` GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); // 对象池配置类,可以根据需要进行自定义配置 poolConfig.setMaxTotal(maxClientCount); // 设置池中最大允许存储的client对象数量 EsClientPoolFactory esClientPoolFactory = new EsClientPoolFactory(); // 要池的对象的工厂类,需要实现创建和销毁client对象的逻辑 GenericObjectPool<TransportClient> clientPool = new GenericObjectPool<>(esClientPoolFactory, poolConfig); // 利用对象工厂类和配置类生成对象池 TransportClient client = clientPool.borrowObject(); // 从池中获取一个client对象 // 使用client对象进行操作 clientPool.returnObject(client); // 使用完毕后归还对象给池 ``` 通过池ElasticsearchClient,可以有效地管理和复用client对象,提高资源利用率和性能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [apache common pool2对象池应用之elasticsearch TransportClient](https://blog.csdn.net/fantasticqiang/article/details/80388070)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [EsClientPoolFactory.java(es连接池工厂类)](https://download.csdn.net/download/zxrautu1234/11716313)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值