通过调用 jdbcTemplate.getDataSource().getConnection()显式获 取一个连接,这个连接不是 logon() 方法事务上下文线程绑定的连接,所以如果开发者如果没 有手工释放这连接(显式调用 Connection#close() 方法),则这个连接将永久被占用(处于 active 状态),造成连接泄漏!下面,我们编写模拟运行的代码,查看方法执行对数据连接的 实际占用情况:
清单 2.JdbcUserService.java:模拟运行代码
…
@Service("jdbcUserService")
public class JdbcUserService {
…
//①以异步线程的方式执行 JdbcUserService#logon()方法,以模拟多线程的环境
public static void asynchrLogon(JdbcUserService userService, String userName) {
UserServiceRunner runner = new UserServiceRunner(userService, userName);
runner.start();
}
private static class UserServiceRunner extends Thread {
private JdbcUserService userService;
private String userName;
public UserServiceRunner(JdbcUserService userService, String userName) {
this.userService = userService;
this.userName = userName;
}
public void run() {
userService.logon(userName);
}
}
//② 让主执 行线程睡眠一段指定的时间
public static void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//③ 汇报数据源的连接占用情况
public static void reportConn(BasicDataSource basicDataSource) {
System.out.println("连接数[active:idle]-[" +
basicDataSource.getNumActive()+":"+basicDataSource.getNumIdle()+"]");
}
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext ("user/connleak/applicatonContext.xml");
JdbcUserService userService = (JdbcUserService) ctx.getBean("jdbcUserService");
BasicDataSource basicDataSource = (BasicDataSource) ctx.getBean ("dataSource");
//④汇报数据源初始连接占用情况
JdbcUserService.reportConn(basicDataSource);
JdbcUserService.asynchrLogon(userService, "tom");
JdbcUserService.sleep(500);
//⑤此时线程A正在执行 JdbcUserService#logon()方法
JdbcUserService.reportConn (basicDataSource);
JdbcUserService.sleep(2000);
// ⑥此时线程A所执行的JdbcUserService#logon()方法已经执行完毕
JdbcUserService.reportConn(basicDataSource);
JdbcUserService.asynchrLogon(userService, "john");
JdbcUserService.sleep(500);
//⑦此时线程B正在执行 JdbcUserService#logon()方法
JdbcUserService.reportConn (basicDataSource);
JdbcUserService.sleep(2000);
// ⑧此时线程A和B都已完成JdbcUserService#logon()方法的执行
JdbcUserService.reportConn(basicDataSource);
}
Spring事务管理高级应用难点剖析: 第3部分(3)
时间:2012-04 |