• 技术文章 >Java >java教程

    java中正确使用ThreadLocal的实例代码分析

    黄舟黄舟2017-03-27 10:11:49原创819
    这篇文章主要介绍了java 中ThreadLocal 的正确用法的相关资料,需要的朋友可以参考下

    java 中ThreadLocal 的正确用法

    用法一:在关联数据类中创建private static ThreadLocalThreaLocal的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;
      }
      
    }

    以上就是java中正确使用ThreadLocal的实例代码分析的详细内容,更多请关注php中文网其它相关文章!

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    专题推荐:java,ThreadLocal
    上一篇:java基于反射得到对象属性值的示例代码分享 下一篇:Java中ArrayList自定义模仿源码的示例
    大前端线上培训班

    相关文章推荐

    • 理解java8中java.util.function.*pojo反射新方法(附代码)• 浅析安卓app和微信授权登录及分享完整对接(代码分享)• 教你一招搞定时序数据库在Spring Boot中的使用• 一招教你使用java快速创建Map(代码分享)• PlayFramework 完整实现一个APP(十一)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网