随笔-57  评论-202  文章-17  trackbacks-0
      使用Jakarta Commons Pool可以根据需要快速的实现自己的对象池,只需要实现PoolableObjectFactory或者KeyedPoolableObjectFactory接口。KeyedPoolableObjectFactory和PoolableObjectFactory的不同之处在于KeyedPoolableObjectFactory的每个方法都比PoolableObjectFactory多了一个Object key的参数,使用这个参数可以使得对象池中的每个对象都有所不同。
      PoolableObjectFactory定义了五个方法(摘至Jakarta Commons Pool API文档):
  1. makeObject is called whenever a new instance is needed.
  2. activateObject is invoked on every instance before it is returned from the pool.
  3. passivateObject is invoked on every instance when it is returned to the pool.
  4. destroyObject is invoked on every instance when it is being "dropped" from the pool (whether due to the response from validateObject, or for reasons specific to the pool implementation.)
  5. validateObject is invoked in an implementation-specific fashion to determine if an instance is still valid to be returned by the pool. It will only be invoked on an "activated" instance. 


      下面是我的一个SocketChannel对象池的实现,实现了KeyedPoolableObjectFactory接口。

package sample.pool;

import java.net.SocketAddress;
import java.nio.channels.SocketChannel;

import org.apache.commons.pool.KeyedPoolableObjectFactory;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Company: </p>
 *
 * @author George Hill
 * @version 1.0
 
*/


public class SocketPoolableObjectFactory implements KeyedPoolableObjectFactory {

    
/**
     * 创建新的对象
     * @param key Object 创建对象需要用到的参数
     * @return Object SocketChannel实例
     * @throws Exception
     
*/

    
public Object makeObject(Object key) throws Exception {
    SocketAddress address 
= (SocketAddress) key;

    
// 创建SocketChannel
    SocketChannel channel = SocketChannel.open(address);

    
return channel;
  }


  
/**
   * 销毁对象
   * @param key Object 创建对象时的参数
   * @param obj Object 需要销毁的对象
   * @throws Exception
   
*/

  
public void destroyObject(Object key, Object obj) throws Exception {
    SocketChannel channel 
= (SocketChannel) obj;

    
if (channel != null)
      channel.close();
    channel 
= null;
  }


  
/**
   * 检验对象是否有效
   * @param key Object 创建对象时的参数
   * @param obj Object 需要进行检验的对象
   * @return boolean 有效返回true,无效返回false
   
*/

  
public boolean validateObject(Object key, Object obj) {
    SocketChannel channel 
= (SocketChannel) obj;

    
if (channel != null && channel.isOpen() && channel.isConnected())
      
return true;

    
return false;
  }


  
/**
   * 将对象激活,这里不需要做任何工作
   * @param key Object
   * @param obj Object
   * @throws Exception
   
*/

  
public void activateObject(Object key, Object obj) throws Exception {
  }


  
/**
   * 将对象挂起,这里不需要做任何工作
   * @param key Object
   * @param obj Object
   * @throws Exception
   
*/

  
public void passivateObject(Object key, Object obj) throws Exception {
  }


}

      我的测试程序:

package sample.pool;

import java.io.IOException;
import java.net.
*;
import java.nio.ByteBuffer;
import java.nio.channels.
*;
import java.util.
*;

import org.apache.commons.pool.
*;
import org.apache.commons.pool.impl.
*;

/**
 * <p>Title: 测试的线程类</p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2005</p>
 *
 * <p>Company: </p>
 *
 * @author George Hill
 * @version 1.0
 
*/


public class TestThread implements Runnable {

  
// 线程名称
  private String name;

  
// 对象池
  private KeyedObjectPool pool;

  
// 连接的网络地址
  private InetSocketAddress address;

  
public TestThread(String name, KeyedObjectPool pool,
                    InetSocketAddress address) 
{
    
this.name = name;
    
this.pool = pool;
    
this.address = address;
  }


  
public void run() {
    System.
out.println(name + ": Client Start");
    SocketChannel channel 
= null;

    
try {
      channel 
= (SocketChannel) pool.borrowObject(address);
    }

    
catch (Exception ex) {
      ex.printStackTrace();
    }


    
// 从对象池中借出对象成功
    if (channel != null{
      System.
out.println(name + ": Borrow Channel successfully!");

      
try {
        channel.configureBlocking(
false);

        
// 创建Selector
        Selector selector = Selector.open();
        
// 向Selector注册我们需要的READ事件
        SelectionKey skey = channel.register(selector, SelectionKey.OP_READ);

        boolean stop 
= false;
        
int n = 0;
        
int read = 0;
        ByteBuffer buffer 
= ByteBuffer.allocate(1024);

        System.
out.println("Client Start");

        
// 轮询
        while (!stop) {
          
// 获取Selector返回的时间值
          n = selector.select();

          
// 当传回的值大于0事,读事件发生了
          if (n > 0{
            Set 
set = selector.selectedKeys();
            Iterator it 
= set.iterator();

            
while (it.hasNext()) {
              skey 
= (SelectionKey) it.next();
              it.remove();

              
if (skey.isReadable()) {
                SocketChannel sc 
= (SocketChannel) skey.channel();

                
while ( (read = sc.read(buffer)) != -1{
                  
if (read == 0{
                    
break;
                  }


                  buffer.flip();
                  
byte[] array = new byte[read];
                  buffer.
get(array);
                  String s 
= new String(array);
                  System.
out.print(s);
                  buffer.clear();

                  
if (s.indexOf("new"!= -1{
                    stop 
= true;
                    System.
out.println();
                  }

                }

              }

            }

          }

        }

      }

      
catch (IOException ioe) {
        ioe.printStackTrace();
      }


      
try {
        pool.returnObject(address, channel);
      }

      
catch (Exception ex) {
        ex.printStackTrace();
      }

    }


    System.
out.println(name + ": Client Stop");
  }


  
/**
   * 测试方法
   * @param args String[] 控制台参数
   * @throws Exception
   
*/

  
public static void main(String[] args) throws Exception {
    SocketPoolableObjectFactory factory 
= new SocketPoolableObjectFactory();
    StackKeyedObjectPoolFactory poolFactory 
= new StackKeyedObjectPoolFactory(factory);
    KeyedObjectPool pool 
= poolFactory.createPool();

    
// 创建连接清华BBS的线程
    Thread t1 = new Thread(new TestThread("清华", pool, new InetSocketAddress("bbs.tsinghua.edu.cn"23)));
    t1.start();
    
// 创建连接华南理工BBS的线程
    Thread t2 = new Thread(new TestThread("华南理工", pool, new InetSocketAddress("bbs.gznet.edu.cn"23)));
    t2.start();
  }


}



      参考资料:
      1. Jakarta Commons Pool网站:http://jakarta.apache.org/commons/pool/
      2. IBM开发者的一篇很好的文章《使用Jakarta Commons Pool处理对象池化》
posted on 2005-05-20 14:08 小米 阅读(4059) 评论(0)  编辑  收藏 所属分类: Java

只有注册用户登录后才能发表评论。


网站导航: