与数据库建立连接是很耗费资源和时间的,所以可以提前建立好一些连接,将它们放入到一个容器中,比如数组,等待需要使用的时候取出,用完再放回。这样一来就解决了许多问题,比如:只有一个连接,此时正在执行查询的动作,但是需要查询返回的内容有很多,需要一段时间才能结束,但又需要执行插入的动作,那在查询没有结束的时候,插入是执行不了的,引入连接池之后,一个动作使用一条连接,互相就不会受到很大的影响了。
先把连接池的类构建好
public ConnPool{
private ArrayList<Connection> array = new ArrayList();//用于放置连接对象的容器
//定义这个构造方法,使其创建对象的时候就就建立好指定数量的连接,并将这些连接放入到容器中
public ConnPool(String DriverName,String url,String userName,String password,int size)throws Exception{
Class.forName(DriverName);
for(int i = 0;i < size;i++){
Connection conn = DriverManager.getConnection(url,userName,passwprd);
array.add(conn);//建立好连接就将其加入到容器中
}
}
//取一个连接的时候,将其从容器中移去,给方法加static关键字,不需要实例化就能调用方法,便于测试
public static Connection getOne(){
return array.remove(0);
}
public static void freeConn(Connection conn){
array.add(conn);
}
//得到当前池中可用的连接个数
public int getSizeOfConn(){
return array.size();
}
}
用户类
public class User {
private int ID;
private String name;
public User(int ID,String name) {
this.ID = ID;
this.name = name;
}
public int getID() {
return ID;
}
public void setID(int iD) {
ID = iD;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
运行类
public class Manager implements Runnable {
//向数据库中存入信息
public synchronized void saveUser(User u,Connection connection) throws Exception {
String sql = "insert into test1 (id,name) values("+u.getID()+",'"+u.getName()+"');";
Connection conn = connection;
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);
}
//让每一个线程去存储一次用户信息
public void run() {
for(int i = 0;i < 10;i++) {
Connection conn = ConnPool.getOne();
User u = new User(i,"i");
try {
saveUser(u,conn);
ConnPool.freeConn(conn);
System.out.println(Thread.currentThread().getName()+"保存用户数据成功"+"Conn为"+conn);
Thread.sleep(10);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("保存用户数据失败");
}
}
}
public static void main(String[] args) {
try {
//建立一个连接池的对象,并初始化连接个数为3
ConnPool cp = new ConnPool("com.mysql.cj.jdbc.Driver","jdbc:mysql://数据库地址:3306/cyh", "cyh1314", "密码",3);
Manager m = new Manager();
//创建三个线程,让他们同时去存储信息,观察连接对象的使用情况
for(int i = 1;i < 4;i++) {
Thread t = new Thread(m,"【线程"+i+"】");
t.start();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行后的结果如下:
尾号为ccdf的连接对象都被线程1、2、3分别使用过,也就证明咱们的这个连接池建立成功了。
当然后续还可以在很多地方上进行优化,比如给连接池使用生产消费模型,当前可用个数小于一定值的时候,就让他再创建一些连接出来,但这之后,如果可用个数超过一定值,就移除一些,实现连接池大小的弹性变化。