Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
连接池的java实现_Java_Multithreading_Performance_Connection_Pool - Fatal编程技术网

连接池的java实现

连接池的java实现,java,multithreading,performance,connection,pool,Java,Multithreading,Performance,Connection,Pool,我正在实现一个连接池(JDBC连接和SMPP连接)。我知道有几个经过良好测试的连接池。但我只想自己实现。 我在多线程环境中使用它。这更符合我个人的兴趣。我的实现是这样的。 我创建一个ConcurrentLinkedQueue并将连接推送到队列。 每次线程请求连接时,连接都会从队列中弹出。 作业完成后,线程将连接推回到队列。 我的连接轮询实现类如下所示 import java.util.concurrent.ConcurrentLinkedQueue; import org.apache.log

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

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");
        }
    }

}
import java.util.concurrent.ConcurrentLinkedQueue;
导入org.apache.log4j.Logger;
导入org.jsmpp.bean.BindType;
导入org.jsmpp.bean.NumberingPlanIndicator;
导入org.jsmpp.bean.TypeOfNumber;
导入org.jsmpp.session.BindParameter;
导入org.jsmpp.session.SMPPSession;
公共类SMPPConnectionPool{
静态ConcurrentLinkedQueue connectionPool=null;
静态记录器日志=null;
静止的
{
LOG=LogManager.getLogger(SMPPConnectionPool.class);
connectionPool=新的ConcurrentLinkedQueue();
}
/*此方法从队列返回会话。如果队列中不存在会话,则将创建并返回新会话。
*此方法使用QueryParams APi从gparams读取与加密相关的数据
* */
公共静态SMPPSession getConenction()
{
SMPPSession session=connectionPool.poll();
if(会话!=null)
{
System.out.println(“Thread”+Thread.currentThread().getName()+“get”+session.getSessionId());
LOG.info(“Thread”+Thread.currentThread().getName()+“get”+session.getSessionId());
返回会议;
}
其他的
{
SMPPSession SMPPSession=新SMPPSession();
试一试{
String host=queryparams.getGparamAsString(NotificationConstants.SMSC_host);
int port=queryparams.getGparamAsInteger(NotificationConstants.SMSC_port);
字符串systemId=QueryParams.GetGParamAssString(NotificationConstants.SMSC_系统_ID);
字符串密码=QueryParams.GetGParamaString(NotificationConstants.SMSC_密码);
如果(主机==null | |系统ID==null | |密码==null | |端口==0)
{
String errorMessage=“以下参数为空\n”;
if(主机==null){
errorMessage=errorMessage+“主机为空”;
}
if(systemId==null){
errorMessage=errorMessage+“系统ID为空”;
}
如果(密码==null){
errorMessage=errorMessage+“密码为空”;
}
如果(端口==0){//TODO需要更改此值,如果未指定端口号时QueryParams API不会返回零
errorMessage=errorMessage+“端口为空”;
}
抛出新异常(errorMessage);
}
smppSession
.connectAndBind(主机、端口、新绑定参数(
BindType.BIND_TRX,系统ID,
密码,“,
类型编号。未知,
NumberingPlanIndicator.UNKNOWN,null));
LOG.info(“会话已创建,会话id为”+smppSession.getSessionId());
}捕获(例外e){
LOG.error(CommonUtilities.getExceptionString(e));
}
System.out.println(“Thread”+Thread.currentThread().getName()+“got”+smppSession.getSessionId());
LOG.info(“Thread”+Thread.currentThread().getName()+“get”+smppSession.getSessionId());
返回smppSession;
}
}
//此方法将conenction推回队列,以使其可用于其他线程。
公共静态无效推送会话(SMPPSession SMPPSession)
{
布尔值isInserted=connectionPool.offer(smppSession);
如果(已插入)
{
LOG.info(“将会话推回到队列”);
System.out.println(“将上下文推回到队列”);
}
其他的
{
LOG.info(“将会话推回队列失败”);
System.out.println(“未能将会话推回队列”);
}
}
公共静态会话()
{
while(connectionPool!=null&&connectionPool.size()>0)
{
SMPPSession session=connectionPool.poll();
session.unbindAndClose();
LOG.info(“结束会话”);
}
}
}
我只想知道这个实现的问题。请给出建议。我想对JDBC连接池实现做同样的操作。boolean isInserted=connectionPool.offer(smppSession);随后的分析没有意义,因为ConcurrentLinkedQueue是无界的,并且它的offer()总是返回true。见API

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

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

static ConcurrentLinkedQueue<SMPPSession> connectionPool = new ConcurrentLinkedQueue<SMPPSession>();
static Logger LOG = LogManager.getLogger(SMPPConnectionPool.class);
5) 这似乎可疑

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

您捕获异常并继续,就好像一切正常一样

我在实现中看到的一些问题如下:

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

  • 在网络中断的情况下,数据源和客户端之间的TCP连接可能会中断。因此,池持有的连接将过时。似乎不存在“刷新”连接的机制。许多连接池框架提供了要执行的测试连接
    } catch (Exception e) {
        LOG.error(CommonUtilities.getExceptionString(e));
    }
    System.out.println("Thread "+Thread.currentThread().getName() +" got "+smppSession.getSessionId());