java 中ThreadLocal 的正确用法

网友投稿 177 2023-05-30


java 中ThreadLocal 的正确用法

java 中ThreadLocal 的正确用法

用法一:在关联数据类中创建private static ThreadLocalThreaLocal的JDK文档中说明:ThreadLocal instances are typically private static fields in classes that wish to associate state whttp://ith 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 = sessionFactoMZkaVGXaZsry.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()方法获取要操作的数据,这样可以保证每个线程对应一个数据对象,在任何时刻都操作的是这个对象。

public class ThreadLocalTest implements Runnable{

ThreadLocal studenThreadLocal = new ThreadLocal();

@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;

}

}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:vue2.0实战之使用vue
下一篇:Java事务管理学习之JDBC详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~