在JAVA开发中,主要使用到两种可称为池的技术。
1、线程池
2、连接池
其中线程池是指:把一个或多个线程通过统一的方式进行调度和重复使用的技术,避免了因为线程过多而带来使用上的开销。
连接池:一般指数据库的连接。将数据库连接作为对象存储在内存中,当用户需要访问数 据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。
1、线程池:
主要好处:
- 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 提高线程的可管理性。
已封装的组件有ThreadPoolExecutor
可使用进行线程池的创建
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(4), new NameTreadFactory(), new MyIgnorePolicy());
构造方法参数:

调用:
executor.execute(new Runnable() {
@Override
public void run() {
//
}
});
2、数据库连接池
已经有封装的组件有:
DBCP连接池:
package com.oracle.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import org.apache.commons.dbcp.BasicDataSource;
import com.oracle.vo.Student;
//通用的数据库操作类
public class BaseDao {
Connection conn;
PreparedStatement stmt;
ResultSet rs;
ResultSetMetaData rsmd;
static String driver ;
static String url;
static String user;
static String password;
static String initSize;
static String minIdle;
static String maxActive;
static BasicDataSource pool;
static {
ResourceBundle bundle = ResourceBundle.getBundle("db");
driver = bundle.getString("driver");
url = bundle.getString("url");
user = bundle.getString("user");
password = bundle.getString("password");
initSize = bundle.getString("initSize");
minIdle = bundle.getString("minIdle");
maxActive = bundle.getString("maxActive");
pool = new BasicDataSource();
pool.setDriverClassName(driver);
pool.setUrl(url);
pool.setUsername(user);
pool.setPassword(password);
pool.setInitialSize(Integer.parseInt(initSize));
pool.setMinIdle(Integer.parseInt(minIdle));
pool.setMaxActive(Integer.parseInt(maxActive));
}
public int insert(String sql,Object[] values) {
getConnection();
int result = 0;
try {
stmt = conn.prepareStatement(sql);
for(int i = 0;i<values.length;i++) {
stmt.setObject(i+1, values[i]);
}
result = stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
public int update(String sql,Object[] values) {
return insert(sql,values);
}
public int delete(String sql,Object[] values) {
return insert(sql,values);
}
//按条件查询
//结果集的数据向 vo中填充属性 通过接口 描述填充的过程
public <T> List<T> select(String sql,Object[] values,Convert<T> convert){
List<T> list = new ArrayList<T>();
getConnection();
try {
stmt = conn.prepareStatement(sql);
for(int i = 0;i<values.length;i++) {
stmt.setObject(i+1, values[i]);
}
rs = stmt.executeQuery();
while(rs.next()) {
T t = convert.convert(rs);
list.add(t);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
//按id查询
public <T> T selectById(String sql,Object[] values,Convert<T> convert) {
getConnection();
try {
stmt = conn.prepareStatement(sql);
for(int i = 0;i<values.length;i++) {
stmt.setObject(i+1, values[i]);
}
rs = stmt.executeQuery();
if(rs.next()) {
return convert.convert(rs);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return null;
}
//获得连接
public Connection getConnection() {
try {
conn = pool.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void main(String[] args) {
//向学生表插入一条记录
/*String sql = "insert into student(sname,tel,amt) values(?,?,?)";
Object[] values = new Object[] {"abc","13111111111",1000};
CommonData cdata = new CommonData();
System.out.println(cdata.insert(sql, values));*/
//id是35的学生电话修改为11111111111
/*String sql = "update student set tel=? where id=?";
Object[] values = new Object[] {"11111111111",35};
CommonData cdata = new CommonData();
System.out.println(cdata.update(sql, values));*/
String sql = "delete from student where id = ?";
Object[] values = new Object[] {35};
BaseDao cdata = new BaseDao();
System.out.println(cdata.delete(sql, values));
//显示所有学生的姓名和电话号
List<Student> list = cdata.select("select * from student", new Object[] {}, new
StudentConvert());
for(Student s:list) {
System.out.println(s.getSname());
}
Student s = cdata.selectById("select * from student where id=?", new Object[] {21}, new
StudentConvert());
System.out.println(s.getSname());
/* List<Student> list = cdata.select("select * from student", new Object[] {},(rs)-> {
Student s = new Student();
try {
s.setId(rs.getInt("id"));
s.setAmt(rs.getInt("amt"));
s.setSname(rs.getString("sname"));
} catch (SQLException e) {
e.printStackTrace();
}
return s;
});*/
}
}
class StudentConvert implements Convert<Student> {
@Override
public Student convert(ResultSet rs) {
Student s = new Student();
try {
s.setId(rs.getInt("id"));
s.setAmt(rs.getInt("amt"));
s.setSname(rs.getString("sname"));
s.setBirthday(rs.getDate("birthday"));
} catch (SQLException e) {
e.printStackTrace();
}
return s;
}
}
public class Test {
public static void main(String[] args) {
BasicDataSource pool = new BasicDataSource();
pool.setDriverClassName("com.mysql.jdbc.Driver");
pool.setUrl("jdbc:mysql://localhost:3306/java2113?characterEncoding=utf8");
pool.setUsername("root");
pool.setPassword("root");
pool.setInitialSize(3);
pool.setMinIdle(3);
pool.setMaxActive(5);
try {
Connection conn = pool.getConnection();
System.out.println(conn.isClosed());
} catch (SQLException e) {
e.printStackTrace();
}
}
}
C3P0连接池:
先对dbcp连接池稳定,但速度慢。
基本配置项:

Druid连接池:
配置:
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!--jdbc_url是AnalyticDB for MySQL集群的连接地址URL,可以在控制台的集群信息页面获取连接URL。-->
<property name="url" value="${jdbc_url}" />
<!--jdbc_user是AnalyticDB for MySQL集群中的用户账号:高权限账号或者普通账号。-->
<property name="username" value="${jdbc_user}" />
<!--jdbc_password是AnalyticDB for MySQL集群中用户账号对应的密码。-->
<property name="password" value="${jdbc_password}" />
<!--配置初始化连接池大小、最小连接数、最大连接数。-->
<property name="initialSize" value="5" />
<property name="minIdle" value="10" />
<property name="maxActive" value="20" />
<!--配置获取连接等待超时的时间。-->
<property name="maxWait" value="60000" />
<!--配置一个连接在连接池中的最小生存时间、最大生存时间,超过最大生存时间会被移除,单位毫秒。-->
<property name="minEvictableIdleTimeMillis" value="600000" />
<property name="maxEvictableIdleTimeMillis" value="900000" />
<!--配置间隔多久进行一次检测,检测需要关闭的空闲连接,单位毫秒。 默认是60s,太长可能会导致无法及时检测到连接中断。-->
<property name="timeBetweenEvictionRunsMillis" value="2000" />
<!--配置从连接池获取连接时,当连接空闲时间大于timeBetweenEvictionRunsMillis时是否检查连接有效性,true每次都检查;false不检查。-->
<property name="testWhileIdle" value="true" />
<!--配置从连接池获取连接时和向连接池归还连接时,是否检查连接有效性。-->
<!--每次获取或归还连接都检测太频繁,除非特别重要或网络特别不可靠等情况,建议用testWhileIdle + timeBetweenEvictionRunsMillis代替。-->
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!--配置是否定期探活、探活间隔。-->
<property name="keepAlive" value="true" />
<property name="keepAliveBetweenTimeMillis" value="30000" /> <!--默认120s。-->
<!--配置一个连接最大使用次数,避免长时间使用相同连接造成服务器端负载不均衡。-->
<property name="phyMaxUseCount" value="1000" />
<!--探活、验证链接有效性的查询,新版本默认使用mysqlPing代替-->
<property name="validationQuery" value="select 1" />
<!--配置监控统计拦截的filters。-->
<property name="filters" value="stat" />
</bean>
阿里巴巴开发的连接池,优点:对SQL语句进行监控、拦截的功能。
线程池和连接池是Java中常见的两种资源管理技术,它们在并发编程和系统性能优化方面有着重要的应用。下面将对这两种技术进行详细解释。
一、线程池
线程池是一种用于管理线程的机制,它可以在程序启动时预先创建一定数量的线程,并将这些线程放入线程池中。当程序需要执行新任务时,线程池会从线程池中取出一个线程来执行任务,任务完成后线程不会立即销毁,而是返回到线程池中等待下一个任务的到来。这样可以大大减少线程的创建和销毁开销,提高系统的性能和响应速度。
在Java中,可以使用java.util.concurrent包中的Executor框架来实现线程池。Executor框架提供了一些类和接口,用于创建和管理线程池。其中最常用的类是ThreadPoolExecutor类,它提供了丰富的构造器参数来配置线程池。可以通过设置线程池的corePoolSize、maximumPoolSize、keepAliveTime、workQueue等参数来控制线程池的行为。
二、连接池
连接池是一种用于管理数据库连接的机制,它可以在程序启动时预先创建一定数量的数据库连接,并将这些连接放入连接池中。当程序需要执行数据库操作时,连接池会从连接池中取出一个连接来执行操作,操作完成后连接不会立即关闭,而是返回到连接池中等待下一个操作的到来。这样可以大大减少数据库连接的创建和关闭开销,提高系统的性能和响应速度。
在Java中,可以使用第三方库如HikariCP、C3P0、DBCP等来实现连接池。这些库提供了丰富的配置参数来控制连接池的行为。可以通过设置连接池的最大连接数、最小连接数、超时时间等参数来满足系统的性能需求。
总之,线程池和连接池都是为了优化系统性能而设计的资源管理技术。通过合理地使用这两种技术,可以提高系统的响应速度和处理能力,减少资源的浪费和消耗。
本文深入解析Java中的线程池(如ThreadPoolExecutor)与数据库连接池(如DBCP、C3P0、Druid)的原理、实现与优势,探讨如何通过它们提高系统性能和响应速度。
683

被折叠的 条评论
为什么被折叠?



