用法一:在关联数据类中创建private static ThreadLocal
ThreaLocal的JDK文档中说明:ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread。如果我们希望通过某个类将状态(例如用户ID、事务ID)与线程关联起来,那么通常在这个类中定义private static类型的ThreadLocal 实例。
例如,在下面的类中,私有静态 ThreadLocal 实例(serialNum)为调用该类的静态 SerialNum.get() 方法的每个线程维护了一个“序列号”,该方法将返回当前线程的序列号。(线程的序列号是在第一次调用 SerialNum.get() 时分配的,并在后续调用中不会更改。)
- public class SerialNum {
- // The next serial number to be assigned
- private static int nextSerialNum = 0;
- private static ThreadLocal serialNum = new ThreadLocal() {
- protected synchronized Object initialValue() {
- return new Integer(nextSerialNum++);
- }
- };
- public static int get() {
- return ((Integer) (serialNum.get())).intValue();
- }
- }
【例】
public class ThreadContext {
private String userId;
private Long transactionId;
private static ThreadLocal threadLocal = new ThreadLocal(){
@Override
protected ThreadContext initialValue() {
return new ThreadContext();
}
};
public static ThreadContext get() {
return threadLocal.get();
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Long getTransactionId() {
return transactionId;
}
public void setTransactionId(Long transactionId) {
this.transactionId = transactionId;
}
}
用法二:在Util类中创建ThreadLocal
这是上面用法的扩展,即把ThreadLocal的创建放到工具类中。
【例】例如Hibernate的工具类:
public class HibernateUtil {
private static Log log = LogFactory.getLog(HibernateUtil.class);
private static final SessionFactory sessionFactory; //定义SessionFactory
static {
try {
// 通过默认配置文件hibernate.cfg.xml创建SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
log.error("初始化SessionFactory失败!", ex);
throw new ExceptionInInitializerError(ex);
}
}
//创建线程局部变量session,用来保存Hibernate的Session
public static final ThreadLocal session = new ThreadLocal();
/**
* 获取当前线程中的Session
* @return Session
* @throws HibernateException
*/
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
// 如果Session还没有打开,则新开一个Session
if (s == null) {
s = sessionFactory.openSession();
session.set(s); //将新开的Session保存到线程局部变量中
}
return s;
}
public static void closeSession() throws HibernateException {
//获取线程局部变量,并强制转换为Session类型
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}
private static Log log = LogFactory.getLog(HibernateUtil.class);
private static final SessionFactory sessionFactory; //定义SessionFactory
static {
try {
// 通过默认配置文件hibernate.cfg.xml创建SessionFactory
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
log.error("初始化SessionFactory失败!", ex);
throw new ExceptionInInitializerError(ex);
}
}
//创建线程局部变量session,用来保存Hibernate的Session
public static final ThreadLocal session = new ThreadLocal();
/**
* 获取当前线程中的Session
* @return Session
* @throws HibernateException
*/
public static Session currentSession() throws HibernateException {
Session s = (Session) session.get();
// 如果Session还没有打开,则新开一个Session
if (s == null) {
s = sessionFactory.openSession();
session.set(s); //将新开的Session保存到线程局部变量中
}
return s;
}
public static void closeSession() throws HibernateException {
//获取线程局部变量,并强制转换为Session类型
Session s = (Session) session.get();
session.set(null);
if (s != null)
s.close();
}
}
用法三:在Runnable中创建ThreadLocal
还有一种用法是在线程类内部创建ThreadLocal,基本步骤如下:
1、在多线程的类(如ThreadDemo类)中,创建一个ThreadLocal对象threadXxx,用来保存线程间需要隔离处理的对象xxx。
2、在ThreadDemo类中,创建一个获取要隔离访问的数据的方法getXxx(),在方法中判断,若ThreadLocal对象为null时候,应该new()一个隔离访问类型的对象,并强制转换为要应用的类型。
3、在ThreadDemo类的run()方法中,通过调用getXxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。
2、在ThreadDemo类中,创建一个获取要隔离访问的数据的方法getXxx(),在方法中判断,若ThreadLocal对象为null时候,应该new()一个隔离访问类型的对象,并强制转换为要应用的类型。
3、在ThreadDemo类的run()方法中,通过调用getXxx()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。
public class ThreadLocalTest implements Runnable{
ThreadLocal<Studen> studenThreadLocal = new ThreadLocal<Studen>();
@Override
public void run() {
String currentThreadName = Thread.currentThread().getName();
System.out.println(currentThreadName + " is running...");
Random random = new Random();
int age = random.nextInt(100);
System.out.println(currentThreadName + " is set age: " + age);
Studen studen = getStudent(); //通过这个方法,为每个线程都独立的new一个student对象,每个线程的的student对象都可以设置不同的值
studen.setAge(age);
System.out.println(currentThreadName + " is first get age: " + studen.getAge());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( currentThreadName + " is second get age: " + studen.getAge());
}
private Studen getStudent() {
Studen studen = studenThreadLocal.get();
if (null == studen) {
studen = new Studen();
studenThreadLocal.set(studen);
}
return studen;
}
public static void main(String[] args) {
ThreadLocalTest t = new ThreadLocalTest();
Thread t1 = new Thread(t,"Thread A");
Thread t2 = new Thread(t,"Thread B");
t1.start();
t2.start();
}
}
class Studen{
int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
ThreadLocal<Studen> studenThreadLocal = new ThreadLocal<Studen>();
@Override
public void run() {
String currentThreadName = Thread.currentThread().getName();
System.out.println(currentThreadName + " is running...");
Random random = new Random();
int age = random.nextInt(100);
System.out.println(currentThreadName + " is set age: " + age);
Studen studen = getStudent(); //通过这个方法,为每个线程都独立的new一个student对象,每个线程的的student对象都可以设置不同的值
studen.setAge(age);
System.out.println(currentThreadName + " is first get age: " + studen.getAge());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println( currentThreadName + " is second get age: " + studen.getAge());
}
private Studen getStudent() {
Studen studen = studenThreadLocal.get();
if (null == studen) {
studen = new Studen();
studenThreadLocal.set(studen);
}
return studen;
}
public static void main(String[] args) {
ThreadLocalTest t = new ThreadLocalTest();
Thread t1 = new Thread(t,"Thread A");
Thread t2 = new Thread(t,"Thread B");
t1.start();
t2.start();
}
}
class Studen{
int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
相关推荐
正确理解ThreadLocal.pdf
主要介绍了java 中ThreadLocal 的正确用法的相关资料,需要的朋友可以参考下
ThreadLocal 用法详解.md
ThreadLocal入门教程。 讲解了线程安全和ThreadLocal的使用的基本知识。
ThreadLocal
理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal
ThreadLocal应用示例及理解,这个写了相关的示例,可以参考一下。
学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!
DbUTils中用ThreadLocal类
主要介绍ThreadLocal的原理,实例分析以及注意事项
主要介绍了Java ThreadLocal用法,结合实例形式详细分析了ThreadLocal线程局部变量相关原理、定义与使用方法,需要的朋友可以参考下
java 简单的ThreadLocal示例
ThreadLocal的几种误区ThreadLocal的几种误区ThreadLocal的几种误区
Synchronized与ThreadLocal
本例以序列号生成的程序为例,展示ThreadLocal的使用
设计模式及ThreadLocal详细讲解资料,想要学习java或者提升自己技术的同学可以下载观看
ThreadLocal保证一个类的实例变量在各个线程中都有一份单独的拷贝, 从而不会影响其他线程中的实例变量
详解java底层实现原理,ThreadLocal底层实现的数据结构,为什么不会导致内存泄露
JDBC事务的封装和Threadlocal实例,参考博客:http://blog.csdn.net/daijin888888/article/details/50988053