`
aniu2008
  • 浏览: 42724 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java中ThreadLocal类的使用

阅读更多
EasyDBO的数据库连接部分,为了给每个连接提供上下文,程序用到了一个关键的类——ThreadLocal。

什么是ThreadLocal?

顾名思义它是local variable(线程局部变量)。它的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。

使用场景

To keep state with a thread (user-id, transaction-id, logging-id) To cache objects which you need frequentlyThreadLocal类

它主要由四个方法组成initialValue(),get(),set(T),remove(),其中值得注意的是initialValue(),该方法是一个protected的方法,显然是为了子类重写而特意实现的。该方法返回当前线程在该线程局部变量的初始值,这个方法是一个延迟调用方法,在一个线程第1次调用get()或者set(Object)时才执行,并且仅执行1次。ThreadLocal中的确实实现直接返回一个null:

ThreadLocal的原理

ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。比如下面的示例实现:

public class ThreadLocal
{
 private Map values = Collections.synchronizedMap(new HashMap());
 public Object get()
 {
  Thread curThread = Thread.currentThread();
  Object o = values.get(curThread);
  if (o == null && !values.containsKey(curThread))
  {
   o = initialValue();
   values.put(curThread, o);
  }
  return o;
 }

 public void set(Object newValue)
 {
  values.put(Thread.currentThread(), newValue);
 }

 public Object initialValue()
 {
  return null;
 }
}

ThreadLocal 的使用

使用方法一:

Hibernate的文档时看到了关于使ThreadLocal管理多线程访问的部分。具体代码如下

1.  public static final ThreadLocal session = new ThreadLocal();
2.  public static Session currentSession() {
3.      Session s = (Session)session.get();
4.      //open a new session,if this session has none
5.   if(s == null){
6.      s = sessionFactory.openSession();
7.      session.set(s);
8.   }
      return s;
9. }

我们逐行分析
1。 初始化一个ThreadLocal对象,ThreadLocal有三个成员方法 get()、set()、initialvalue()。
    如果不初始化initialvalue,则initialvalue返回null。
3。session的get根据当前线程返回其对应的线程内部变量,也就是我们需要的net.sf.hibernate.Session(相当于对应每个数据库连接).多线程情况下共享数据库链接是不安全的。ThreadLocal保证了每个线程都有自己的s(数据库连接)。
5。如果是该线程初次访问,自然,s(数据库连接)会是null,接着创建一个Session,具体就是行6。
6。创建一个数据库连接实例 s
7。保存该数据库连接s到ThreadLocal中。
8。如果当前线程已经访问过数据库了,则从session中get()就可以获取该线程上次获取过的连接实例。

使用方法二

当要给线程初始化一个特殊值时,需要自己实现ThreadLocal的子类并重写该方法,通常使用一个内部匿名类对ThreadLocal进行子类化,EasyDBO中创建jdbc连接上下文就是这样做的:

public class JDBCContext{
private static Logger logger = Logger.getLogger(JDBCContext.class);
private DataSource ds;
protected Connection connection;
private boolean isValid = true;
private static ThreadLocal jdbcContext;

private JDBCContext(DataSource ds){
  this.ds = ds;
  createConnection(); 
}
public static JDBCContext getJdbcContext(javax.sql.DataSource ds)

  if(jdbcContext==null)jdbcContext=new JDBCContextThreadLocal(ds);
  JDBCContext context = (JDBCContext) jdbcContext.get();
  if (context == null) {
   context = new JDBCContext(ds);
  }
  return context;
}

private static class JDBCContextThreadLocal extends ThreadLocal {
  public javax.sql.DataSource ds;
  public JDBCContextThreadLocal(javax.sql.DataSource ds)
  {
   this.ds=ds;
  }
  protected synchronized Object initialValue() {
   return new JDBCContext(ds);
  }
}
}

使用单例模式,不同的线程调用getJdbcContext()获得自己的jdbcContext,都是通过JDBCContextThreadLocal 内置子类来获得JDBCContext对象的线程局部变量,这个变量是该线程所独有的。
分享到:
评论

相关推荐

    Java中ThreadLocal的设计与使用

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,用于为每个线程提供独立的变量副本。理解ThreadLocal的工作原理和使用方法对于编写高效、安全的多线程程序至关重要。 ### ...

    java中ThreadLocal详解

    在Java多线程编程中,`ThreadLocal`是一个非常重要的工具类,它提供了一种在每个线程内部存储线程私有实例的方法。通常情况下,当多个线程共享某个变量时,可能会引发线程安全问题。而`ThreadLocal`则提供了另一种...

    简单分析Java线程编程中ThreadLocal类的使用共

    Java线程编程中的ThreadLocal类是一个非常重要的工具,它在多线程环境下提供了一种线程局部变量的机制。ThreadLocal并非是简单的变量,而是一种能够确保每个线程都拥有独立副本的变量容器。理解ThreadLocal的工作...

    java事务 - threadlocal

    当Java事务与ThreadLocal结合使用时,可以在不同的线程中维护各自的事务状态,比如在Spring框架中,每个线程的ThreadLocal可以存储一个TransactionStatus对象,这样就可以在线程内部管理当前事务的状态,而不会影响...

    JAVA ThreadLocal类深入

    在这个例子中,getSession()方法会检查ThreadLocal中是否存在Session,若不存在则创建并设置,而closeSession()方法则负责关闭并移除当前线程的Session副本。 总结来说,ThreadLocal是Java中解决多线程数据隔离问题...

    java 简单的ThreadLocal示例

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,尤其在处理线程间数据隔离和共享时。ThreadLocal不是线程本身,而是为每个线程提供一个独立的变量副本,使得每个线程都可以独立地改变...

    Java 中ThreadLocal类详解

    Java中的ThreadLocal类是一个强大的工具,它允许程序员创建线程局部变量。这意味着每个线程都有其自己独立的、不可见的变量副本,从而避免了线程间的数据共享问题,简化了多线程环境下的编程复杂性。ThreadLocal并不...

    java ThreadLocal多线程专属的变量源码

    java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多线程专属的变量源码java ThreadLocal多...

    使用Java ThreadLocal.docx

    以下是一个完整的ThreadLocal示例,演示了如何在一个Runnable实例中使用ThreadLocal: ```java public class ThreadLocalExample { public static class MyRunnable implements Runnable { private ThreadLocal...

    Java ThreadLocal详解_动力节点Java学院整理

    ThreadLocal的实现原理是基于Java的类加载机制。在每个线程中,ThreadLocal会创建一个变量副本,并将其存储在ThreadLocalMap中。ThreadLocalMap是一个特殊的HashMap,它将ThreadLocal变量与线程关联起来。 ...

    java 中ThreadLocal 的正确用法

    ThreadLocal 是 Java 中的一个特殊类,它可以让每个线程拥有自己独立的变量副本,避免了多线程之间的共享变量问题。下面我们将详细介绍 Java 中 ThreadLocal 的正确用法。 用法一:在关联数据类中创建 private ...

    Java ThreadLocal类应用实战案例分析

    Java ThreadLocal类是Java语言中的一种线程局部变量机制,允许每个线程都拥有自己的变量副本,从而避免了多线程之间的变量冲突。在本文中,我们将通过实战案例分析Java ThreadLocal类的应用、原理、用法及相关操作...

    Java中ThreadLocal源码详细注释

    线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突...

    ThreadLocal应用示例及理解

    在ThreadLocal中,`set()`方法用于设置当前线程的ThreadLocal变量值,`get()`方法用于获取当前线程的ThreadLocal变量值。 ```java threadLocal.set("Hello, ThreadLocal"); String value = threadLocal.get(); ``` ...

    Java源码解析ThreadLocal及使用场景

    在这个场景中,不能使用ThreadLocal类,因为ThreadLocal适用的场景是,多个线程都需要使用一个变量,但这个变量的值不需要在各个线程间共享,各个线程都只使用自己的这个变量的值。 ThreadLocal还能解决一个参数...

    java 中ThreadLocal实例分析

    Java 中的 ThreadLocal 实例分析是指在多线程环境下,如何使用 ThreadLocal 来实现线程安全。ThreadLocal 是 Java 中的一种机制,用于在多个线程中实现变量的隔离。 在上面的代码中,我们可以看到,ConsumeClientA ...

    快速了解Java中ThreadLocal类

    ThreadLocal类位于`java.lang`包下,其设计目标是为每个线程提供一种便捷的方式,来存储与该线程相关的数据。每个ThreadLocal实例都有一个与之关联的线程局部变量,每个线程都可以通过`get()`方法获取属于自己的变量...

    深入理解 Java 之 ThreadLocal 工作原理1

    ThreadLocal是Java中用于线程局部变量的一个工具类,它的工作原理主要体现在如何在不同的线程之间隔离变量的副本,确保每个线程拥有自己的独立数据。这个设计模式在多线程编程中尤其有用,因为它避免了传统的同步...

    入研究java.lang.ThreadLocal类.docx

    ### 知识点详解:Java.lang.ThreadLocal 类 #### 一、概述 **ThreadLocal** 并非线程的一种特殊实现形式,而是一种为每个线程提供独立副本的机制,通常被称为“线程局部变量”。这种机制使得每个线程都可以独立...

Global site tag (gtag.js) - Google Analytics