赞
踩
池化思想是我们项目开发过程中的一种非常重要的思想,如整数池,字符串池,对象池、 连接池、线程池等都是池化思想的一种应用,都是通过复用对象,以减少因创建和释放对象 所带来的资源消耗,进而来提升系统性能。
说明:
因为如果不采用池化思想,每次需要使用该对象,就需要创建一个该对象,当然如果不使用该对象了,就需要调用GC。GC在销毁该对象时,需要调用CPU,此时会占用一些资源。如果使用池化思想,创建过的对象就放到池中,下次需要使用时,复用该对象就可以了,一定程度上减少了资源的占用
Integer整数池案例:
public class IntegerTests{
public static void main(String[] args) {
//演示整数池(-128~+127)
Integer n1=100;//Integer.valueOf(100)
Integer n2=100;
//对整数而言为什么不将所有整数都放到池中,而只是存储了一部分数据呢?
//池设计的目的是?以空间换时间,这块空间中应该存储一些常用的整数数据
Integer n3=200;//new Integer(200)
Integer n4=200;
System.out.println(n1==n2);//true
System.out.println(n3==n4);//false
//所有池的设计都会用到一种设计模式:享元模式 (通过池复用对象)
}
}
项目开发过程中应用程序与数据库交互时,“获得连接”或“释放连接”是非常消耗系 统资源的两个过程,频繁地进行数据库连接的建立和关闭会极大影响系统的性能,若多线程 并发量很大,这样耗时的数据库连接就可能让系统变得卡顿。因为 TCP 连接的创建开支十 分昂贵,并且数据库所能承载的 TCP 并发连接数也有限制,针对这种场景,数据库连接池应运而生。(数据库连接池复用的对象是“连接”)
图示:
对“频繁地进行数据库连接的建立和关闭会极大影响系统的性能”的理解:
进行数据库连接的”建立“与"关闭"的操作需要基于TCP协议去实现,因此每次的”建立“与"关闭"都需要三次握手及四次挥手,对cpu资源的占用比较大,如果频繁的进行数据库交互,并发量变大,系统就会出现卡顿等情况,一定程度上影响了系统的性能。
Java 官方,为了在应用程序中更好的应用连接池技术,定义了一套数据源规范,例如 javax.sql.DataSource 接口,基于这个接口,很多团队或个人创建了不同的连接池对象。
然后我们的应用程序中通过耦合与 DataSource 接口,便可以方便的切换不同厂商的连接池。Java 项目中通过连接池获取连接的一个基本过程,如图所示:
用户通过 DataSource 对象的 getConnection()方法,获取一个连接。
假如池中有连接,则直接将连接返回给用户。
假如池中没有连接,则会调用 Dirver(驱动, 由数据库厂商进行实现)对象的 connect 方法从数据库获取,拿到连接以后,可以将连接在池中放一份,然后将连接返回给调用方。
连接需求方再次需要连接时,可以从池中获取, 用完以后再还给池对象。
数据库连接池在 Java 数据库相关中间件产品群中,应该算是底层最基础的一类产品, 作为企业应用开发必不可少的组件,无数天才们为我们贡献了一个又一个的优秀产品,它们有的随时代发展,功成身退,有的则还在不断迭代,老而弥坚,更有新生代产品,或性能无 敌,或功能全面。目前市场上常见的连接池有 DBCP、C3P0,DRUID,HikariCP 等。
在系统初始化的时候,在内存中开辟一片空间,将一定数量的数据库连接作为对象存储 在对象池里,并对外提供数据库连接的获取和归还方法。
用户访问数据库时,并不是建立一 个新的连接,而是从数据库连接池中取出一个已有的空闲连接对象;使用完毕归还后的连接 也不会马上关闭,而是由数据库连接池统一管理回收,为下一次借用做好准备。
如果由于高并发请求导致数据库连接池中的连接被借用完毕,其他线程就会等待,直到有连接被归还。 整个过程中,连接并不会关闭,而是源源不断地循环使用,有借有还。
数据库连接池还可以 通过设置其参数来控制连接池中的初始连接数、连接的上下限数,以及每个连接的最大使用 次数、最大空闲时间等,也可以通过其自身的管理机制来监视数据库连接的数量、使用情况 等。
数据库连接池以连接池的管理为核心,主要支持连接池的建立和释放这两大核心功能。
“麻雀虽小,五脏俱全”,数据库连接池还可以支持其他非常实用的功能。一款商用的数据库 连接池、一款能够被开发者广泛使用的数据库连接池、一款能够在开源社区持续活跃发展的 数据库连接池还必须再支持一些实用的功能,如并发(锁性能优化乃至无锁)、连接数控制 (不同的系统对连接数有不同的需求)、监控(一些自身管理机制来监视连接的数量及使用 情况等)、外部配置(各种主流数据库连接池官方文档最核心的部分)、资源重用(数据库连 接池的核心思想)、检测及容灾(面对一些网络、时间等问题的自愈)、多库多服务(如不同 的数据库、不同的用户名和密码、分库分表等情况)、事务处理(对数据库的操作符合 ALLALL-NOTHING 原则)、定时任务(如空闲检查、最小连接数控制)、缓存(如 PSCache 等避 免对 SQL 重复解析)、异常处理(对 JDBC 访问的异常统一处理)、组件维护(如连接状态、 JDBC 封装的维护)等。
案例:
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; /** * 通过此单元测试类获取数据源对象,并且通过数据对象获取数据库连接 * @SpringBootTest 注解描述的类 * 为springboot中的单元测试类 * 说明: * 1)springboot中的单元测试类必须放在启动类所在包- * -或子包中 * 2)springboot中的单元测试类必须使用@SpringBootTest注解描述 */ @SpringBootTest public class DataSourceTests { /** * 在项目中添加了数据库相关依赖以后,springboot底层会自动帮我们配置一个 * 数据源(DataSource)对象,此对象是连接池的规范. * @Autowired注解描述属性时,是告诉spring框架,要基于反射机制为属性赋值(依赖注入) * 赋值时,首先会基于属性类型从spring容器查找相匹配的对象, 假如只有一个则直接注入, * 有多个相同类型的对象时,还会比较属性名(检测属性名是否与bean名字相同),有相同的 * 则直接注入(没有相同的直接抛出异常.) */ @Autowired private DataSource dataSource; @Test //org.junit.jupiter.api.Test void getConnections() throws SQLException { //获取链接时,会基于dataSource获取连接池对象,进而从池中获取连接 Connection conn = dataSource.getConnection(); System.out.println(conn); //结果:HikariProxyConnection@773518491 wrapping com.mysql.cj.jdbc.ConnectionImpl@3fd2322d } }
<!--链接 mysql 时使用的 mysql 驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--当添加 data-jdbc 依赖时会自动下载 HikariCp 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
#application.pepoerties文件
#Spring DataSource 配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db_notice?serverTimezone=GMT%2B8&charsetEnconding=utf8;
spring.datasource.username=root
spring.datasource.password=123456
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; import java.sql.Statement; @SpringBootTest public class JdbcTests { @Autowired private DataSource dataSource; @Test void testInsert() throws SQLException { //JDBC (是java中推出的连接数据库的一组API,是规范) //数据库厂商提供JDBC驱动(jdbc规范的实现)负责实现数据库的操作. //1.建立连接 (负责与数据库进行通讯) Connection conn = dataSource.getConnection(); //2.创建statement(sql传送器->负责与将sql发送到数据库端) Statement stat = conn.createStatement(); //准备sql语句 String sql="insert into sys_notice " + " (title,content,type,status,createdTime,createdUser,modifiedTime,modifiedUser) " + " values ('加课通知','本周六加课','1','0',now(),'xiaj',now(),'xiaj') "; //3.发送sql stat.execute(sql); //4.处理结果 //5.释放资源(后续释放资源要写到finally代码块中) stat.close(); conn.close(); } }
以上,仅供学习参考
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。