对象复用------“池”之数据库连接池和线程池

对象池化是目前非常常用的一种系统优化技术。

在程序中使用数据库连接池和线程池,可以有效地改善系统在高并发下的性能。

数据库连接池

目前应用较为广泛的数据库连接池组件有C3PO和Proxool。其中C3PO是伴随着Hibernate一起发布,与Hibernate联系紧密的数据库连接池。

若在Hibernate中使用C3PO连接池,只需要将C3PO的jar包复制到开发环境中,并且在hibernate.cfg.xml中加入以下配置项即可:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

   <session-factory>

		<property name="connection.username">root</property>
		<property name="connection.password">root</property>
		<property name="connection.url">
			jdbc:mysql://172.21.78.121:3306/utconf?useUnicode=true
			&amp;characterEncoding=UTF-8&amp;mysqlEncoding=utf8
		</property>
		<property name="dialect">
			org.hibernate.dialect.MySQLDialect
		</property>
		<property name="connection.driver_class">
			com.mysql.jdbc.Driver
		</property>
		<property name="hibernate.show_sql">
			true
		</property>
		<property name="hibernate.cache.use_second_level_cache">false</property>  
		<property name="hibernate.current_session_context_class">thread</property>
		<property name="hibernate.jdbc.batch_size">20</property>
		<property name="default_catalog">utconf</property>
		
		<property name="connection.provider_class">
			org.hibernate.connection.C3P0ConnectionProvider
		</property>
		<property name="connection.autoReconnect">true</property>  
        <property name="connection.autoReconnectForPools">true</property>  
        <property name="connection.is-connection-validation-required">true</property>  
		<!-- 最大连接数 -->
		<property name="hibernate.c3p0.max_size">20</property>
		<!-- 最小连接数 -->
		<property name="hibernate.c3p0.min_size">5</property>
		<!-- 获得连接的超时时间,如果超过这个时间,会抛出异常,单位毫秒 -->
		<property name="hibernate.c3p0.timeout">120</property>
		<!-- 最大的PreparedStatement的数量 -->
		<property name="hibernate.c3p0.max_statements">100</property>
		<!-- 每隔120秒检查连接池里的空闲连接 ,单位是秒-->
		<property name="hibernate.c3p0.idle_test_period">120</property>
		<!-- 当连接池里面的连接用完的时候,C3P0一下获取的新的连接数 -->
		<property name="hibernate.c3p0.acquire_increment">2</property>
		<!-- 每次都验证连接是否可用 -->
		<property name="hibernate.c3p0.validate">true</property>

		<mapping resource="com/utstar/mtassis/dbbean/Deviceparameter.hbm.xml" />
		<mapping resource="com/utstar/mtassis/dbbean/Userrole.hbm.xml" />
		<mapping resource="com/utstar/mtassis/dbbean/Userinfo.hbm.xml" />

	</session-factory>

</hibernate-configuration>

当然,也可以脱离Hibernate单独在应用程序中使用C3PO。以下代码构造了一个C3PO的数据库连接池,并从中获得一个数据库连接:

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.DataSources;

public final class DBConnectionPoolDemo {

	public static Object getInnter(Object con){
		Object re=null;
		Field f;
		try {
			f = con.getClass().getDeclaredField("inner");
			f.setAccessible(true);
			re= f.get(con);   //取得内部包装的Connection
			f.setAccessible(false);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return re;
	}
	
	public static void main(String[] argv) {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			DataSource unpooled = DataSources
					.unpooledDataSource(
							"jdbc:mysql://127.0.0.1:3306/test",
							"root", "");
			DataSource pooled = DataSources.pooledDataSource(unpooled);
			//DataSource pooled =unpooled;
			Connection con = null;
			Statement stmt = null;
			ResultSet rs = null;

			con = pooled.getConnection(); //第一次取得数据库连接
			System.out.println("con Class Type is:"+con.getClass().getName());
			Object o1=getInnter(con);  //取得内部的实际数据库连接
			System.out.println("Inner con Class Type is:"+o1.getClass().getName());
			
			stmt = con.createStatement();
			rs = stmt.executeQuery("SELECT * FROM user");
			while (rs.next())
				System.out.println("Data from DB:"+rs.getString(1));
			rs.close();
			stmt.close();
			con.close();
			
			Thread.sleep(1000);  //等待连接返回池中
			con = pooled.getConnection();  //第二次取得数据库连接
			Object o2=getInnter(con);
			if(o1==o2)  //相同,则说明数据库连接被复用
				System.out.println("o1 and o2 is same object.");
			stmt = con.createStatement();
			rs = stmt.executeQuery("SELECT * FROM user");
			while (rs.next())
				System.out.println("Data from DB:"+rs.getString(1));
			rs.close();
			stmt.close();
			con.close();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	static void attemptClose(ResultSet o) {
		try {
			if (o != null)
				o.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	static void attemptClose(Statement o) {
		try {
			if (o != null)
				o.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	static void attemptClose(Connection o) {
		try {
			if (o != null)
				o.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private DBConnectionPoolDemo() {
	}
}

线程池

在Apache中,已经提供了一个Jakarta Commons Pool对象池组件,可以直接使用。

Java中提供了Thread对象和Runnable接口用于创建进程内的线程。其次,为了优化并行程序性能,JDK还提供了java.util.concurrent并发包,内置各种多线程性能优化工具和组件,如线程池、各种并发数据结构等

猜你喜欢

转载自blog.csdn.net/pbyang_love/article/details/81546042