数据库连接池实例-1(基础线程池)

数据库连接池实例-1(基础线程池)

 


前言

数据库连接池进行由浅到深的分项,打算进行三个模块,分别为:基础线程池(自己写了解基本原理),主流线程池配置使用,线程池比较与优化

 

一、数据库连接池存在原因

我们都了解到,数据库获取连接与关闭连接是非常消耗内存的,所以这样不如创建多个连接,将连接放入到一起,在需要使用的时候,拿出连接,进行使用,能够极大的减少内存消耗,同时提高效率。 具体的,设计模式中有一个 资源池设计模式,就是针对池进行设计的,可参考链接 https://www.cnblogs.com/shoshana-kong/p/11249000.html

二、例子

我是使用ArrayList用来存放我的连接,首先创建抽象类,AbsrtDataBase<T>,它的属性主要由两个:lockedList,UnlockedList分别存放,被使用的连接,和空闲的连接。

创建类:DataBase 继承AbsrtDataBase<T> 抽象类,在实现具体的代码。DataBase 类我设置成为单例模式,我们只需要一个数据库连接池没有必要多个。checkOut(),checkIn() 进行线程上锁,ArrList 为线程不安全的,必须上锁。

 

代码如下:

AbsrtDataBase<T>抽象类代码

import java.util.ArrayList;

/*
 * 抽象类
 * 资源连接池
 */
public abstract class AbsrtDataBase<T> {

	ArrayList<T> lockedList, UnlockedList; // 存放的 连接对象

	public AbsrtDataBase() {

	}

	/**
	 * 批量添加
	 */
	public void batchadd() {
		for (int i = 0; i < 10; i++) {
			T t = add();
			this.UnlockedList.add(t);
		}
	}

	/*
	 * 从UnlockedList中取出使用
	 */
	public abstract T checkOut() throws Exception;

	/**
	 * 把数据库连接放回池中(UnlockedList中)
	 * 
	 * @param t
	 * @return
	 * @throws Exception
	 */
	public abstract boolean checkedIn(T t) throws Exception;

	// 往池中添加连接
	public abstract T add();

	// 移除即关闭连接
	public abstract boolean remove(T t);

}

DataBase的代码: 主要通过读取文件,赋值,创建实例,创建线程进行读取。

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Properties;

public class DataBase extends AbsrtDataBase<Connection> {
	private Long expiredTime=(long) 30000;//逾期时间  
	protected int initCon = 20;//初始默认值
	private int maxCon =300;// 最大值
	private int idleCon = 20;//空闲值
	private int addnum = 0;
	private int removenum =0;
	private String url;
	private String name;
	private String password;
	private String type;
	private File proFile;
	private String unCode = "gbk";
	private String fileUrl = "C:/Users/DELL/Desktop/setting.property";

	private static DataBase database ;
	
	public static void main(String[] args){
		DataBase database = null ;
		try {
			database = DataBase.getInstance(); 
			database.getinit();
			database.init();                                                                              
			
		} catch (Exception e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		
		for(int i = 0;i<10;i++){
		Thread thread1 = new TestThread(database);//创建线程
		Thread thread2 = new TestThread2(database);//创建线程
		//启动线程
		thread1.start();
		thread2.start();
			
		}
		
		
	}
	
	public void getinit() throws Exception {
		proFile = new File(fileUrl);
		if (proFile.exists()) {
			FileInputStream fileinputStream = new FileInputStream(proFile);
			InputStreamReader streamReader = new InputStreamReader(
					fileinputStream, unCode);
			Properties props = new Properties();
			props.load(streamReader);
			Field[] fields = DataBase.class.getDeclaredFields();

			// 进行赋值
			for (Field field : fields) {
				String name = field.getName();// 获取类属性
				String value = props.getProperty(name); // 查找到对应的值
				Object type = field.getType();// 获取参数属性
				String typeName = type.toString();// 获取参数类的名称属性;
				System.out.println(typeName);
				if (value != null) {
					// 校验是否为String类型
					if (typeName.indexOf("String") > 0) {
						field.set(database, value);
					}
					// 检验是否为整形
					if (typeName.indexOf("Int") > 0) {
						int valueint = Integer.parseInt(value);
						field.set(database, valueint);
					}
					// 检验是否为长整形
					if (typeName.indexOf("long") > 0) {
						Long valuelong = Long.getLong(value);
						field.set(database, valuelong);
					}

				}
			}

		}
	};
	
   /*
    * 单例模式只允许使用一个实例
    */
	public static synchronized DataBase getInstance() throws Exception {
		if (database == null) {
			database = new DataBase();
			
		}
		return database;
	}

	private DataBase() throws Exception  {
		super();
		
	}

	public void init(){
		
		lockedList = new ArrayList<Connection>(initCon);
		UnlockedList = new ArrayList<Connection>(idleCon);
		
		for(int i=0;i<this.initCon;i++){
			Connection t = add();
			super.UnlockedList.add(t);
		}
		
	}
	


	@Override
	public Connection add() {
		// TODO 自动生成的方法存根
		Connection connection = null;
		try {
			connection = DriverManager.getConnection(url, name, password);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return connection;
	}

	@Override
	public boolean remove(Connection t) {
		// TODO 自动生成的方法存根
		boolean flage = true; // 标志是否成功
		if (t != null) {
			try {
				t.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
				flage = false;
			}
		}
		return flage;

	}
	/**
	 * 将不使用的连接重新放入到 UnlockedList 中
	 */
	@Override
	public synchronized  boolean checkedIn(Connection t) throws Exception {
		removenum++;		
		System.out.println("当前执行数检入"+removenum);		
		int currentLocked = lockedList.size();
		//lockedList不为空的情况下转入
		if(currentLocked!=0){		
		 //将 UnlockedList 中的数据转出到 LockedList 中 
		 t = lockedList.get(currentLocked-1);
		 UnlockedList.add(t);
		 lockedList.remove(currentLocked-1);
		 boolean flage = remove( t);
		 return flage;
		 }else{		
			 throw new Exception("数据量较小不能转出");
			 
		 }
		
	}
	
	/**
	 * 将要被使用的 connection 从池中进行拿出来。
	 */
	@Override
	public Connection checkOut() throws Exception {
		// TODO 自动生成的方法存根		
		addnum++;
		if(UnlockedList.size()==0){
			batchadd();
		};
		System.out.println("当前执行数检出"+addnum);
		
		int currentUnlocked = UnlockedList.size();
		Connection  t = UnlockedList.get(currentUnlocked-1);
		int currentLocked = lockedList.size();
		
		//将unlockedList 的放入到 LockedList中
		if(currentLocked<maxCon){
			lockedList.add(t);
			UnlockedList.remove(t);
			return t;
			
		}else{
			throw new Exception("已经超出了最大连接数");
		}
	
	}

	
	

	
	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public File getProFile() {
		return proFile;
	}

	public void setProFile(File proFile) {
		this.proFile = proFile;
	}

	public String getUnCode() {
		return unCode;
	}

	public void setUnCode(String unCode) {
		this.unCode = unCode;
	}

	public String getFileUrl() {
		return fileUrl;
	}

	public void setFileUrl(String fileUrl) {
		this.fileUrl = fileUrl;
	}

	
}

总结

自己写一个简单的线程池才能了解到,如何去实现线程池,虽然例子很简单,但是可以加深印象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值