首页 > 开发 > Java > 正文

java 中ThreadLocal 的正确用法

2024-07-13 10:05:48
字体:
来源:转载
供稿:网友

javascript/31611.html">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教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表