背景
在Java程序实现中,我们往往应用到事务的机制,在业务层进行事务开启,创建数据库连接,调用Dao层方法进行数据库访问,过程中需要将数据库连接Connection作为参数传递给Dao层方法。显而易见,这样的实现不利于Dao层方法的复用,当在不使用事务的情况下,我们是需要在Dao层方法中创建数据库连接的,这样Dao层方法免去Connection参数就可以使得方法更加独立、明确了,怎样解决这样的尴尬?对于此,我们使用了ThreadLocal进行解决。基本介绍
“本地线程变量”,可以理解为将变量放到ThreadLocal中,同一个线程中共享,多线程之间资源隔离,不相互干扰,保证了线程安全。可将ThreadLocal<T>看作是一个Map类型,可以理解为以存取键值对的方式进行存和取,但需要明确一点的是确定了一个ThreadLocal后,其中就只能存取一个键值对,因此其读和取方法也比较简单了:
get、set方法--为读取、设置线程变量中的值;
remove方法 --移除此线程局部变量当前线程的值;
initialValue--返回此线程局部变量的当前线程初始值。
封装Connection
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 采用ThreadLocal封装Connection
*
* @author Administrator
*
*/
public class ConnectionManager {
//定义ThreadLocal静态变量,确定存取类型为Connection
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();
/**
* 得到Connection
* @return
*/
public static Connection getConnection() {
Connection conn = connectionHolder.get();
//如果在当前线程中没有绑定相应的Connection
if (conn == null) {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:bjpowern";
String username = "drp1";
String password = "drp1";
conn = DriverManager.getConnection(url, username, password);
//将Connection设置到ThreadLocal
connectionHolder.set(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
return conn;
}
/**
* 关闭数据库连接方法
* @return
*/
public static void closeConnection() {
Connection conn = connectionHolder.get();
if (conn != null) {
try {
conn.close();
//从ThreadLocal中清除Connection
connectionHolder.remove();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 关闭数据库连接方法
* @return
*/
public static void close(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Statement pstmt) {
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet rs ) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 事务开启
* @return
*/
public static void beginTransaction(Connection conn) {
try {
if (conn != null) {
if (conn.getAutoCommit()) {
conn.setAutoCommit(false); //手动提交
}
}
}catch(SQLException e) {}
}
/**
* 事务提交
* @return
*/
public static void commitTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.commit();
}
}
}catch(SQLException e) {}
}
/**
* 事务回滚
* @return
*/
public static void rollbackTransaction(Connection conn) {
try {
if (conn != null) {
if (!conn.getAutoCommit()) {
conn.rollback();
}
}
}catch(SQLException e) {}
}
}
经过了以上的封装,ConnectionManager类控制了线程内Connection的创建与获取,就达到了Dao层方法不需要传递Connection参数便可实现业务逻辑层控制事务的效果,ThreadLocal还可以在其他很多情况下应用,在后面的使用中再进行说明。
总结
多线程是解决高并发时常用的技术,明确线程之间的资源共享,合理分配并控制好资源之间的协调,便可以用好多线程,也是应用多线程的前提,在这方面还很欠缺,多多积累学习!