ThreadLocal是线程本地变量,能实现线程范围的共享变量,具体概念这里不在概述。我们知道java web中spring的事务管理能将“service的一个方法调用多次dao里的方法”操作数据库保持在同一事物里。话不多说,来模拟一下事务管理来展示ThreadLocal的作用(不是spring源码,相同思想
):
![微笑](http://static.blog.csdn.net/xheditor/xheditor_emot/default/smile.gif)
package com.ydj;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadLocalDemo {
/**
* 模拟一个用户(即一个线程)调用不同类的方法(使用相同数据库连接)保存数据的过程:(用两个线程进行对比)
* 1.创建数据库连接
* 2.开启事务
* 3.调用A类save方法
* 4.调用B类save方法
* 5.提交事务
* 6.释放数据库连接
*/
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
new Thread(new Runnable() {
@Override
public void run() {
int data = new Random().nextInt(889);
//1
System.out.println(Thread.currentThread().getName() + "创建连接:" + data);
MyConnection myConnection = MyConnection.getInstance();
myConnection.setName("连接:" + data);
//2
myConnection.beginTransaction();
new A().save();//3
new B().save();//4
myConnection.commitTransaction();//5
myConnection.close();//6
}
}).start();
}
}
}
class A {
// 可以直接使用获取到的线程范围内的对象实例调用相应方法
String name = MyConnection.getInstance().getName();
public void save() {
System.out.println(Thread.currentThread().getName() + "调用 A 的save方法,使用"+ name );
}
}
class B {
// 可以直接使用获取到的线程范围内的对象实例调用相应方法
String name = MyConnection.getInstance().getName();
public void save() {
System.out.println(Thread.currentThread().getName() + "调用 B 的save方法,使用"+ name );
}
}
class MyConnection {
//数据连接名
private String name;
// 将数据连接对象(MyConnection)存入当前线程范围内数据集(ThreadLocal)
static ThreadLocal<MyConnection> threadLocal = new ThreadLocal<MyConnection>();
Lock lock = new ReentrantLock();
// 私有化构造方法(单例)
private MyConnection() {};
// 提供获取实例方法
public static MyConnection getInstance() {
MyConnection instance = threadLocal.get();//从当前线程范围内数据集中获取实例对象
if (instance == null) {
instance = new MyConnection();
threadLocal.set(instance);
}
return instance;
}
//模拟开启事务
public void beginTransaction(){
lock.lock();
System.out.println(Thread.currentThread().getName() + "线程,使用"+name+":开启事务");
}
//模拟提交事务
public void commitTransaction(){
lock.unlock();
System.out.println(Thread.currentThread().getName() + "线程,使用"+name+":提交事务");
}
//释放数据连接
public void close(){
System.out.println(Thread.currentThread().getName() + "线程,关闭"+name);
threadLocal.remove();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
运行结果:
Thread-1创建连接:708
Thread-0创建连接:260
Thread-0线程,使用连接:260:开启事务
Thread-1线程,使用连接:708:开启事务
Thread-0调用 A 的save方法,使用连接:260
Thread-1调用 A 的save方法,使用连接:708
Thread-1调用 B 的save方法,使用连接:708
Thread-0调用 B 的save方法,使用连接:260
Thread-1线程,使用连接:708:提交事务
Thread-0线程,使用连接:260:提交事务
Thread-0线程,关闭连接:260
Thread-1线程,关闭连接:708
Thread-0创建连接:260
Thread-0线程,使用连接:260:开启事务
Thread-1线程,使用连接:708:开启事务
Thread-0调用 A 的save方法,使用连接:260
Thread-1调用 A 的save方法,使用连接:708
Thread-1调用 B 的save方法,使用连接:708
Thread-0调用 B 的save方法,使用连接:260
Thread-1线程,使用连接:708:提交事务
Thread-0线程,使用连接:260:提交事务
Thread-0线程,关闭连接:260
Thread-1线程,关闭连接:708
从运行结果能看到可以看到多个类在同一个线程中共享同一份数据