1. 程式人生 > >一個簡易的資料庫連線池

一個簡易的資料庫連線池

目錄

背景

資料庫連線池是比較寶貴的資源,當有大量的連線時,需要使用資料庫連線池來保證資料庫連線資源的複用。

實現原理

通過一個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