一个简易的数据库连接池

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/helloworlddm/article/details/84699405

背景

数据库连接池是比较宝贵的资源,当有大量的连接时,需要使用数据库连接池来保证数据库连接资源的复用。

实现原理

通过一个LinkedList集合来缓存连接的实例,通过等待通知机制来实现获取和释放连接。等待的时间可设置。

具体实现

数据库连接池的实现

package com.genersoft;

import java.sql.Connection;
import java.util.LinkedList;

public class ConnectionPool {
	
	private LinkedList<Connection>   pool = new LinkedList<>();
	//初始化数据库连接池
	public   ConnectionPool(int initialSize)
	{
		
		for (int i = 0;i < initialSize;i++)
		{
			pool.addLast(ConnectionDriver.createConnection());
			//System.out.println(""+pool);
			
		}
	}
	//释放数据库连接池
	public  void releaseConnection(Connection  connection)
	{
		if (connection != null) {
			
			synchronized(pool) {
				pool.addLast(connection);
				pool.notifyAll();
				
			}		
		}	
		
	}
	//获取数据库连接池
	public  Connection   fetchConnection(long  mills) throws InterruptedException
	{
		synchronized(pool)
		{
			if (mills <= 0) {
				
				if (pool.isEmpty())
				{
					
						pool.wait();
					
				}
				return pool.removeFirst();
				
			}
			else {		
				long future = System.currentTimeMillis()+mills;
				long remaining = mills;
				while  (pool.isEmpty() && remaining > 0)
				{
					
						pool.wait(remaining);
						
						remaining = future - System.currentTimeMillis();
					
				}
			
				Connection result = null;
				if (!pool.isEmpty())
				{
					
					result = pool.removeFirst();
				}
				return result;
			}		
		}
	
		
	}

}

Mysql连接的类

package com.genersoft;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;

public class ConnectionDriver {


	public static Connection createConnection() {
		
		String url="jdbc:mysql://localhost:3306/test?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false";

		String user="root";

		String password="root";
		Connection conn = null;

		try {
			 conn =  DriverManager.getConnection(url,user,password);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return conn;
		
		//return  (Connection) Proxy.newProxyInstance(ConnectionDriver.class.getClassLoader(), new Class<?>[] {Connection.class},new Handler() );
	}
	private static class  Handler implements InvocationHandler{

		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			if (method.getName().equals("commit"))
			{
				TimeUnit.MILLISECONDS.sleep(100);
			}
			return null;
		}
		
		
	}
}

测试类:

package com.genersoft;

import java.sql.Connection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Hello world!
 *
 */
public class ConectionPoolTest 
{
	
	private static CountDownLatch start = new CountDownLatch(1);
	private static  CountDownLatch end;
	private static ConnectionPool pool = new ConnectionPool(10);
	
	
    public static void main( String[] args ) throws InterruptedException
    {
       
       int threadNum = 30;
       end = new CountDownLatch(threadNum);
       int  count = 20;
       AtomicInteger  getNum = new AtomicInteger() ;
       AtomicInteger notGetNum = new AtomicInteger() ;
       
       for (int i = 0;i < threadNum;i++)
       {
    	
    	   Thread  runnerThread = new Thread(new RunnerThread(count,getNum,notGetNum),"RunnerThread");
    	   runnerThread.start();
       }    
       start.countDown();
       end.await();
       System.out.println("total invoked"+count*threadNum);
       System.out.println("getNum"+getNum);
       System.out.println("notGetNum"+notGetNum);
   
    }
    
    static class  RunnerThread implements    Runnable{
	   int  count;
       AtomicInteger  getNum ;
       AtomicInteger notGetNum  ;
    	
	  public  RunnerThread(int  count2,AtomicInteger getNum2,AtomicInteger notGetNum2)
	  {
		  this.count = count2;
		  this.getNum = getNum2;
		  this.notGetNum = notGetNum2;	
	  }

	  @Override
	  public void run() {
		  try {
			start.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		  
		while (count > 0)
		{
			
			Connection conn;
		
			try {
				conn = pool.fetchConnection(10);
				
				if (conn != null)
				{
					try {
						conn.createStatement();
						conn.commit();
					}finally {		
						pool.releaseConnection(conn);
						getNum.incrementAndGet();
					}		
				}else {
					
					notGetNum.incrementAndGet();
				}
				
			}catch(Exception e)
			{
				
			}finally {
				
				count--;
			}	
		}
		end.countDown();
	  }
	
    	
    }
}

创建一个表格

一个简单的表格是这么创建的:

线程数量 总获取次数 获取到次数 为获取次数
10 200 200 0
30 600 579 21

猜你喜欢

转载自blog.csdn.net/helloworlddm/article/details/84699405