2013-09-21 67 views
0

我正在实现连接池(JDBC连接和SMPP连接)。我知道有几个经过良好测试的连接池。但我只是想自己实现。 我在多线程环境中使用它。这更多的是我个人的兴趣。我的实现是这样的。 我创建一个ConcurrentLinkedQueue并将连接推送到队列。 每次线程请求连接时,都会从队列中弹出连接。 工作完成后,线程将连接推回队列。 我的连接轮询实现类如下所示。java中的连接池实现

import java.util.concurrent.ConcurrentLinkedQueue; 

import org.apache.log4j.Logger; 
import org.jsmpp.bean.BindType; 
import org.jsmpp.bean.NumberingPlanIndicator; 
import org.jsmpp.bean.TypeOfNumber; 
import org.jsmpp.session.BindParameter; 
import org.jsmpp.session.SMPPSession; 


public class SMPPConnectionPool { 
    static ConcurrentLinkedQueue<SMPPSession> connectionPool = null; 
    static Logger LOG = null; 

    static 
    { 
     LOG = LogManager.getLogger(SMPPConnectionPool.class); 
     connectionPool= new ConcurrentLinkedQueue<SMPPSession>(); 
    } 

    /* This method returns session from queue .If no sessions exist in the queue,then a new session will be created and returned. 
    * This method use QueryGparams APi to read conenction related data from gparams 
    * */ 
    public static SMPPSession getConenction() 
    { 
     SMPPSession session=connectionPool.poll(); 
     if(session!=null) 
     { 
      System.out.println("Thread "+Thread.currentThread().getName() +" got "+session.getSessionId()); 
      LOG.info("Thread "+Thread.currentThread().getName() +" got "+session.getSessionId()); 
      return session; 
     } 
     else 
     { 
      SMPPSession smppSession = new SMPPSession(); 
      try { 
       String host = QueryGparams.getGparamAsString(NotificationConstants.SMSC_HOST); 
       int port = QueryGparams.getGparamAsInteger(NotificationConstants.SMSC_PORT); 
       String systemId = QueryGparams.getGparamAsString(NotificationConstants.SMSC_SYSTEM_ID); 
       String password = QueryGparams.getGparamAsString(NotificationConstants.SMSC_PASSWORD); 
       if(host == null || systemId == null || password == null || port == 0) 
       { 
        String errorMessage = "Following parameters are null \n"; 
        if(host == null) { 
         errorMessage = errorMessage + "host is null"; 
        } 
        if(systemId == null) { 
         errorMessage = errorMessage + "systemId is null"; 
        } 
        if(password == null) { 
         errorMessage = errorMessage + "password is null"; 
        } 
        if(port == 0) { //TODO Need to change this if QueryGParams API will not return zero when port number is not specified 
         errorMessage = errorMessage + "port is null"; 
        } 
        throw new Exception(errorMessage); 
       } 
       smppSession 
       .connectAndBind(host,port, new BindParameter(
         BindType.BIND_TRX, systemId, 
         password, "", 
         TypeOfNumber.UNKNOWN, 
         NumberingPlanIndicator.UNKNOWN, null)); 
       LOG.info("Session has been created.Session id is "+smppSession.getSessionId()); 
      } catch (Exception e) { 
       LOG.error(CommonUtilities.getExceptionString(e)); 
      } 
      System.out.println("Thread "+Thread.currentThread().getName() +" got "+smppSession.getSessionId()); 
      LOG.info("Thread "+Thread.currentThread().getName() +" got "+smppSession.getSessionId()); 
      return smppSession; 
     } 
    } 



    //This method pushes conenction back to queue ,to make it available for other threads. 
    public static void pushConenction(SMPPSession smppSession) 
    { 
     boolean isInserted=connectionPool.offer(smppSession); 
     if(isInserted) 
     { 
      LOG.info("Pushed the conenction back to queue"); 
      System.out.println("Pushed the conenction back to queue"); 
     } 
     else 
     { 
      LOG.info("Failed to push the session back to queue"); 
      System.out.println("Failed to push the session back to queue"); 
     } 
    } 
    public static void closeSessions() 
    { 
     while(connectionPool!=null && connectionPool.size()>0) 
     { 
      SMPPSession session=connectionPool.poll(); 
      session.unbindAndClose(); 
      LOG.info("Closed the session"); 
     } 
    } 

} 

我只是想知道与这个问题implementation.Please advice.I想要做的JDBC连接池实现

+0

我觉得这个问题最适合在codereview – SpringLearner

回答

0

1)布尔isInserted = connectionPool.offer(smppSession)相同;并且随后的分析没有意义,因为ConcurrentLinkedQueue是无界的,并且它的offer()始终返回true。见API

2)我会使用的BlockingQueue,使线程等待活动线程返回一个连接池,如果达到最大活动threds

3)我会初始化静态字段这样

static ConcurrentLinkedQueue<SMPPSession> connectionPool = new ConcurrentLinkedQueue<SMPPSession>(); 
static Logger LOG = LogManager.getLogger(SMPPConnectionPool.class); 

4)为避免不必要的字符串concatination你可以使用这个成语

if (LOG.isInfoEnabled()) { 
    LOG.info("Thread "+Thread.currentThread().getName() +" got "+smppSession.getSessionId()); 
} 

5)这似乎可疑

} catch (Exception e) { 
    LOG.error(CommonUtilities.getExceptionString(e)); 
} 
System.out.println("Thread "+Thread.currentThread().getName() +" got "+smppSession.getSessionId()); 

你捕获异常,并继续担任如果一切OK

+0

好,感谢您的答复。还有其他问题吗?或建议? – Venkat

+0

增加了几个 –

+0

感谢您的建议。如果我使用静态块初始化静态字段,是否有任何问题? – Venkat

0

一些我与执行所看到的问题有以下几点:

  1. 没有超时配置connectAndBind。在网络分区或数据包丢失的情况下,getConnection调用很可能会卡住。

  2. 如果发生网络中断,数据源和客户端之间的TCP连接可能中断。因此,游泳池所持有的连接将陈旧。似乎没有任何机制可以“刷新”连接。许多连接池框架提供了testConnections,可以在后台执行或者在检查连接之前执行(这当然会增加整个getConnection调用的延迟)以应对此问题。

+0

感谢您的建议。我会照顾上述两点。这个实施还有更多问题吗? – Venkat