Java----连接池的基本原理

连接池的基本原理

文章目录

        • 连接池的基本原理
        • dbcp连接池
        • c3p0连接池
        • 阿里连接池

package com.pool01.pool;

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

public class ConnPool {

    private static final String DRIVER = "com.mysql.jdbc.Driver";
    private static final String URL = "jdbc:mysql://localhost/emp?"
        + "useUnicode = true&characterEncoding=utf-8";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "123456";

    //1.连接池需要放很多连接的池子,连接池只要用于让用户拿连接或放(还)连接
    //ArrayList查比较快,LinkedList放比较快;所以连接池选用LinkedList
    LinkedList<Connection>  list = new LinkedList<Connection>();

    //2.获取与数据库之间的连接
    static{
        try {
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //通过构造方法创建连接并把连接放入集合(池子)
    public ConnPool(){
        for (int i = 0; i < 10; i++) {
            try {
                Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
                list.add(conn);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //3.提供一个从池子里面拿连接的方法(将最后一个元素返回给用户)
    public Connection getConnection(){
        Connection conn = null;
        if(list.size() <= 0){
            try {
                conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }else{		
            conn = list.removeLast();
        }
        return conn;
    }

    //4.还连接的方法
    public void close(Connection conn){
        list.addFirst(conn);
    }
}

dbcp连接池

package com.pool02.dbcp;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSourceFactory;

public class DBUtil {

    //1.dbcp获取连接的类DataSource
    private  DataSource ds = null;

    //2.利用构造函数读取配置文件
    public DBUtil(){

        //2-1.怎么读进来(读到代码中)
        InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");

        //2-2.读进来放到哪里
        Properties pp = new Properties();

        //2-3.向流一样读进来,对接到配置文件上
        try {
            pp.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //2-4.初始化ds--利用工厂模式
        try {
            ds = BasicDataSourceFactory.createDataSource(pp);
        } catch (Exception e) {
            e.printStackTrace();
        }	
    }

    //3.创建连接,并包装在一个方法里面
    public Connection getConn(){
        Connection conn = null;
        try {
            conn = ds.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return conn;
    }
}

c3p0连接池

package com.pool03.c3p0;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class ConnDB {

    private static ComboPooledDataSource ds = null;
    private Connection conn = null;

    static {
        if(ds == null){
            ds = new ComboPooledDataSource();
        }	
        try {
            ds.setDriverClass("com.mysql.jdbc.Driver");
            ds.setJdbcUrl("jdbc:mysql://localhost:3306/emp");
            ds.setUser("root");
            ds.setPassword("123456");
            //ds.setMaxPoolSize(100);		
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
    }
    public Connection getconn(){
        if(ds != null){
            try {
                conn = ds.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }		
        }
        return conn;
    }
}

阿里连接池

package com.pool04.druid;
/**
 * 代码调用DruidDataSource来管理连接,
 * 同时声明Threadlocal对象来保存线程请求所获取连接
 * 这样可以避免每一个new一个JDBC对象,将conn对象放在Threadlocal对象中缓存起来,
 * 下一次调用直接从Threadlocal中获取,提高了性能。
 */

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSource;

public class DruidConn {

    //实现数据库连接池的关键对象
    private static DruidDataSource dataSource = new DruidDataSource();

    //声明线程共享变量 		作用:存放创建成功的连接对象
    public static ThreadLocal<Connection > container = new ThreadLocal<Connection>();

    //配置说明
    static{
        //驱动可以不设置,因为可以通过url的值自动搜索
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/emp");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");

        dataSource.setInitialSize(2);		//数据库连接池的初始连接数
        dataSource.setMaxActive(20);	//最大连接数
        dataSource.setMinIdle(5); 		//最小连接数
        //如果超出最大连接数,就会进入对列

        //设置获取连接对象时最大的等待时间(毫秒)
        dataSource.setMaxActive(60000); 	//1分钟

        //用来检测连接是否有效的sql语句
        dataSource.setValidationQuery("SELECT_1");
        dataSource.setTestOnBorrow(false);
        dataSource.setTestWhileIdle(true);

        //PSCache 是否缓存预处理对象
        dataSource.setPoolPreparedStatements(false);	
    }

    /**
	 * 获取数据连接
	 */
    public static Connection getConnection(){
        Connection conn = null;
        //从池中获取连接对象
        try {
            conn = dataSource.getConnection();

            System.out.println(Thread.currentThread().getName() + "~~~获取连接成功!");
            //把获取到连接池对象存储在一个缓冲区
            container.set(conn);
        } catch (SQLException e) {
            System.out.println(Thread.currentThread().getName() + "---获取连接失败!");
            e.printStackTrace();
        }
        return conn;
    }

    /**
	 * 获取当前线程上的连接并开启事务
	 */
    public static void StartTransction (){
        //首先获取当前线程的连接
        Connection conn = container.get();
        if(conn == null){	//如果连接为null
            conn = getConnection();	//创建连接
            container.set(conn);		//将刚刚创建的连接放在线程上
            System.out.println(Thread.currentThread().getName()+"连接为null时,再次创建连接");
        }else{
            System.out.println(Thread.currentThread().getName()+"先线程中拿到连接");
        }

        try {
            conn.setAutoCommit(false);	//手动开启事务
        } catch (SQLException e) {
            e.printStackTrace();
        }   
    }

    /**
	 * 提交事务
	 */
    public static void commit(){
        try {
            Connection conn = container.get(); 		//从当前线程获取连接
            if(conn != null){
                conn.commit();
                System.out.println(Thread.currentThread().getName() + "提交事务");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
	 * 回滚事务
	 */
    public static void rollback(){
        try {
            Connection conn =container.get();
            conn.rollback();	//回滚事务
            container.remove(); //如果回滚了,就移除连接
            System.out.println(Thread.currentThread().getName() + "事务回滚");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    //关闭
    public static void close(){
        try {
            Connection conn = container.get();
            if(conn != null){
                conn.close();
                System.out.println(Thread.currentThread().getName()+"关闭");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e.getMessage(),e);
        }finally{
            try {
                container.remove();	//从当前线程移除连接
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {

        for(int i = 0; i < 4; i++){		
            new Thread(new Runnable() {	
                @Override
                public void run() {
                    Connection conn = DruidConn.getConnection();				
                    DruidConn.StartTransction();
                    System.out.println(Thread.currentThread().getName()+"模拟CRUD");
                    DruidConn.commit();
                    DruidConn.close();
                }
            }).start();
        }
    }
}

你可能感兴趣的:(Java)