您的位置:首页 > 其它

ThreadLocal的正确用法

2015-02-27 15:33 211 查看

用法一:在关联数据类中创建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();

}

}


用法三:在Runnable中创建ThreadLocal

还有一种用法是在线程类内部创建ThreadLocal,基本步骤如下:

1、在多线程的类(如ThreadDemo类)中,创建一个ThreadLocal对象threadXxx,用来保存线程间需要隔离处理的对象xxx。

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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: