自己写了个连接池,不过性能不理想,当模拟1000个线程去连接数据库时,会在getConnection这个方法里爆出空指针。
oracle的配置文件:
driver = oracle.jdbc.driver.OracleDriver url = jdbc:oracle:thin:@localhost:1521:DB user = username password = pwd defaultRowPrefetch=50 defaultExecuteBatch=25 poolsize=20 islation=2
连接池:
package com.connection;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import com.util.PropertiesHelper;
import oracle.jdbc.driver.OracleConnection;
public class ConnectionPool {
private static Map<Connection, Boolean> pool = new HashMap<Connection, Boolean>();
public static DataBase db=null;
private static Properties prop;
private static int POOLSIZE = 5;
public static synchronized void init(String file){
if (pool.size() == 0) {
try {
prop = readProperties(file);
} catch (IOException e) {
e.printStackTrace();
}
try {
Class.forName(prop.getProperty("driver"));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
if (prop.getProperty("poolsize").length() > 0)
POOLSIZE = Integer.parseInt(prop.getProperty("poolsize"));
for (int i = 0; i < POOLSIZE; i++) {
pool.put(newConnection(), true);
}
}
}
private static synchronized Connection newConnection() {
Connection conn=null;
try {
String url=prop.getProperty("url");
conn = DriverManager.getConnection(url, prop);
conn.setTransactionIsolation(Integer.parseInt(prop.getProperty("islation")));
conn.setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void closeAll() {
for (Connection c : pool.keySet()) {
try {
c.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static Connection getConnection() {
synchronized (pool) {
for (Connection conn : pool.keySet()) {
if (pool.get(conn) == false) {
pool.put(conn, true);
return conn;
}
}
}
Connection c=newConnection();
return c;
}
public static void release(Connection conn) {
if (conn != null) {
synchronized (pool) {
if (!pool.keySet().contains(conn)) {
try {
conn.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
} else
pool.put(conn, false);
}
}
}
public static void closePool() {
for (Connection conn : pool.keySet()) {
try {
conn.close();
pool.clear();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
private static Properties readProperties(String file) throws IOException {
Properties result = new Properties();
InputStream is = ConnectionPool.class.getClassLoader()
.getResourceAsStream(file);
result.load(is);
return result;
}
}
测试代码:
package com.test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.connection.ConnectionPool;
import com.dao.BaseDAO;
public class Test extends Thread{
private String sql;
private Connection c;
public Test(Connection c,String sql){
this.c=c;
this.sql=sql;
}
public static void main(String[] args) {
ConnectionPool.init("oracle.properties");
for(int i=0;i<100;i++){
String sql="select sysdate from dual";
new Test(ConnectionPool.getConnection(),sql).start();
}
}
public void run(){
try {
System.out.println(c);
ResultSet rs=c.createStatement().executeQuery(sql);
while(rs.next()){
System.out.println(rs.getString(1));
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
ConnectionPool.release(c);
}
}
}
模拟100个线程完全没问题,但是数量一旦上去了就不行了 连接池得不到连接了。
我的思路是当你请求一个资源,池会看看池中有没有资源,有的话把这个资源分发给请求,没有的话,生成新的资源同时把该资源放到池中。当请求归还的时候,池会判断池中是否满了,如果满了,那么释放该资源。其中关键的,就是生成新资源,判断是否释放资源。
我自己写是为了多学点知识 一直用别人封装好的连接池 没什么意思,个人写的很烂,欢迎有技术性的建议。