ThreadLocal学习
1 ThreadLocal介绍
- ThreadLocal类似Map集合,key-value的数据结构,但ThreadLocal根据当前线程作为key
1
2
3
4
5
6
7
8/** 为当前线程关联一个数据 */
public void set(T value)
/** 获取当前线程关联的数据 */
public T get();
/** 移除当前线程关联的数据 */
public void remove();
- 特点
- 每一个ThreadLocal对象,只能为当前线程关联一个数据
- ThreadLocal对象定义时,一般都是static类型
- ThreadLocal中保存的数据,在线程销毁后,会由JVM自动释放
2 ThreadLocal实现事务
(1)JDBC工具类
- 用ThreadLocal为每个线程分配一个数据库连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79public class JdbcUtils {
private static DataSource dataSource;
private static ThreadLocal<Connection> connes = new ThreadLocal<>();
// 初始化
static {
Properties properties = new Properties();
try {
properties.load(JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties"));
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
System.out.println("log --- 数据库初始化失败!");
e.printStackTrace();
}
}
/**
* 获取连接
* @return connection
*/
public static Connection getConnection() {
// 获取当前线程conn,不存在则创建
Connection conn = connes.get();
if(conn == null) {
try {
conn = dataSource.getConnection();
conn.setAutoCommit(false); // 手动提交事务
connes.set(conn); // 当前线程存储连接
} catch (SQLException throwables) {
System.out.println("log --- 获取连接失败!");
throwables.printStackTrace();
}
}
return conn;
}
/**
* 提交事务,并关闭连接
*/
public static void commitAndClose() {
Connection conn = connes.get();
if (conn != null) {
try {
conn.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
connes.remove();
}
}
}
/**
* 回滚事务,并关闭连接
*/
public static void rollbackAndClose() {
Connection conn = connes.get();
if (conn != null) {
try {
conn.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
connes.remove();
}
}
}
}
- 用ThreadLocal为每个线程分配一个数据库连接
(2)事务过滤器
- 过滤器直接放行请求,执行无异常,调用工具类的提交方法;出现异常,调用工具类的回滚方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class TransactionFilter implements Filter{
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
//事务提交
JdbcUtils.commitAndClose();
} catch (Exception e) {
e.printStackTrace();
// 事务回滚
JdbcUtils.rollbackAndClose();
throw new RuntimeException(e);
}
}
}
- 过滤器直接放行请求,执行无异常,调用工具类的提交方法;出现异常,调用工具类的回滚方法