Java Design Ideas - Pooling - Handwritten Database Connection Pool

Pool: A collection of objects of the same class

The role of connection pool
1. Resource reuse
Because database connections are reused, a lot of performance overhead caused by frequent connection creation and release is avoided. On the basis of reducing system consumption, it also improves the stability of the system running environment (reduces memory fragmentation and the number of temporary database processes/threads).
2. Faster system response speed During the initialization process of the
database connection pool, several database connections are often created and placed in the pool for standby. At this point, the initialization of the connection has been completed. For business request processing, the existing available connections are directly used, which avoids the time overhead of the database connection initialization and release process, thereby reducing the overall response time of the system.
3. New resource allocation method
For systems in which multiple applications share the same database, the database connection pool technology can be used at the application layer through the configuration of database connections. Set the maximum number of database connections available for an application to prevent an application from monopolizing all database resources.
4. Unified connection management to avoid database connection leakage
In a relatively complete database connection pool implementation, connections occupied by timeouts can be forcibly reclaimed according to the preset connection occupancy timeout time. In this way, resource leaks that may occur in conventional database connection operations are avoided (when there is a defect in the program, the connection applied for is forgotten to be closed, at this time, there is a connection leak).

Example

configuration file

jdbcDriver=com.mysql.jdbc.Driver
jdbcurl=jdbc:mysql://localhost:3306/mybatis
userName=root
password=root
initCount=10
stepSize=4
poolMaxSize=150

Database connection wrapper

public class PooledConnection {
    private boolean isBusy = false;
    private Connection connection;

    public Connection getConnection() {
        return connection;
    }

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    public boolean isBusy() {
        return isBusy;
    }

    public void setBusy(boolean isBusy) {
        this.isBusy = isBusy;
    }

    public PooledConnection(Connection connection, boolean isBusy) {
        this.connection = connection;
        this.isBusy = isBusy;
    }

    public void close() {
        this.isBusy = false;
    }

    public ResultSet queryBysql(String sql) {
        Statement sm = null;
        java.sql.ResultSet rs = null;

        try {
            sm = connection.createStatement();
            rs = sm.executeQuery(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return rs;
    }

}

connection pool interface

public interface IMyPool {

    PooledConnection getConnection();

    void createConnection(int count);
}

accomplish

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

public class MyPoolImpl implements IMyPool {

    private static String jdbcDriver = null;
    private static String jdbcUrl = null;
    private static String userName = null;
    private static String password = null;

    private static int initCount;

    private static int stepSize;

    private static int poolMaxSize;

    private static Vector<PooledConnection> pooledConnections = new Vector<>();

    public MyPoolImpl() {

        init();
    }

    private void init() {

        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("jdbc.properties");

        //字节信息 key value 形式化
        Properties pro = new Properties();
        try {
            pro.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        jdbcDriver = pro.getProperty("jdbcDriver");
        jdbcUrl = pro.getProperty("jdbcurl");
        userName = pro.getProperty("userName");
        password = pro.getProperty("password");

        initCount = Integer.valueOf(pro.getProperty("initCount"));
        stepSize = Integer.valueOf(pro.getProperty("stepSize"));
        poolMaxSize = Integer.valueOf(pro.getProperty("poolMaxSize"));

        try {
            Driver mysqlDriver = (Driver) Class.forName(jdbcDriver).newInstance();

            DriverManager.registerDriver(mysqlDriver);

            createConnection(initCount);

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


    }


    public PooledConnection getConnection() {
        if (pooledConnections.size() == 0) {
            System.out.println("获取链接管道失败,原因是连接池中没有可用管道");
            throw new RuntimeException("创建管道对象失败,原因是即将超过最大上限值");
        }
        //连接池中的管道是没有超时  没有其他线程占用
        PooledConnection connection = getRealConnection();

        while (connection == null) {
            createConnection(stepSize);
            connection = getRealConnection();
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return connection;
    }

    @Override
    public void createConnection(int count) {
        if (poolMaxSize > 0 && pooledConnections.size() + count > poolMaxSize) {
            System.out.println("创建管道对象失败,原因是即将超过最大上限值");
            throw new RuntimeException("创建管道对象失败,原因是即将超过最大上限值");
        }

        for (int i = 0; i < count; i++) {
            try {
                Connection conn = DriverManager.getConnection(jdbcUrl, userName, password);

                PooledConnection pooledConnection = new PooledConnection(conn, false);
                pooledConnections.add(pooledConnection);
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
    }

    private synchronized PooledConnection getRealConnection() {
        for (PooledConnection conn : pooledConnections) {
            if (!conn.isBusy()) {
                Connection connection = conn.getConnection();
                try {

                    //发送一个信息给数据库 2000毫秒内  收到返回信息 认为 这个管道没有超时
                    if (!connection.isValid(2000)) {
                        Connection validConn = DriverManager.getConnection(jdbcUrl, userName, password);
                        conn.setConnection(validConn);
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn.setBusy(true);
                return conn;
            }
        }
        return null;
    }

}

Connection pool management

public class PoolManager {

    private static class createPool {

        private static MyPoolImpl poolImpl = new MyPoolImpl();

    }

    /**
     * 内部类单利模式产生使用对象
     * @return
     */
    public static MyPoolImpl getInstance() {
        return createPool.poolImpl;
    }
}

test class

import java.sql.ResultSet;
import java.sql.SQLException;

public class MypoolTest {

    private static MyPoolImpl poolImpl = PoolManager.getInstance();

    public synchronized static void selctData() {
        PooledConnection connection = poolImpl.getConnection();
        ResultSet rs = connection.queryBysql("SELECT * FROM user");
        try {
            while (rs.next()) {
                System.out.println(rs.getString("ID") + "\t\t");
                System.out.println(rs.getString("USERNAME") + "\t\t");
                System.out.println(rs.getString("PASSWORD") + "\t\t");
                System.out.println();
            }
            rs.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        for (int i = 0; i < 1500; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    selctData();
                }
            }).start();
        }
    }

}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325889828&siteId=291194637