ThreadLocal的正确用法_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > ThreadLocal的正确用法

ThreadLocal的正确用法

 2014/9/14 0:57:55  chriszeng87  程序员俱乐部  我要评论(0)
  • 摘要:用法一:在关联数据类中创建privatestaticThreadLocalThreaLocal的JDK文档中说明:ThreadLocalinstancesaretypicallyprivatestaticfieldsinclassesthatwishtoassociatestatewithathread。如果我们希望通过某个类将状态(例如用户ID、事务ID)与线程关联起来,那么通常在这个类中定义privatestatic类型的ThreadLocal实例。例如,在下面的类中
  • 标签:用法 thread 正确

用法一:在关联数据类中创建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()?时分配的,并在后续调用中不会更改。)

?

  1. 1999998092651px; margin-bottom: 0px !important; margin-left: 0px !important; padding-right: 3px !important; padding-left: 10px !important;" class="alt">public?class?SerialNum?{??
  2. ????//?The?next?serial?number?to?be?assigned??
  3. ????private?static?int?nextSerialNum?=?0;??
  4. ??
  5. ????private?static?ThreadLocal?serialNum?=?new?ThreadLocal()?{??
  6. ????????protected?synchronized?Object?initialValue()?{??
  7. ????????????return?new?Integer(nextSerialNum++);??
  8. ????????}??
  9. ????};??
  10. ??
  11. ????public?static?int?get()?{??
  12. ????????return?((Integer)?(serialNum.get())).intValue();??
  13. ????}??
  14. }??


?


【例】

?
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;
????}
????
} ? ? ? ? 转自:http://blog.csdn.net/vking_wang/article/details/14225379
上一篇: sun.misc.Unsafe的几个点 下一篇: 没有下一篇了!
发表评论
用户名: 匿名