java中ThreadLocal

原创 2016年06月02日 11:07:34

ThreadLocal可以为每个线程保存一份数据,相当与线程私有数据,不会被别的线程共享。
Thread.class

ThreadLocal.ThreadLocalMap threadLocals = null;  key为ThreadLocal实例,value要保存的数据

这样可以看得出来每个线程都会拥有一个单独的ThreadLocal.ThreadLocalMap(它是ThreadLocal一个静态内部类)
ThreadLocal.class

 //为当前线程写入值
 public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t); //每个线程都有一个ThreadLocalMap
    if (map != null)
        map.set(this, value);  //更新<ThreadLocal , value>
    else
        createMap(t, value);   //根据当前线程创建ThreadLocalMap
 }
 ThreadLocalMap getMap(Thread t) {
       return t.threadLocals;
 }
 void createMap(Thread t, T firstValue) {
      t.threadLocals = new ThreadLocalMap(this, firstValue);  //充分说明了每个线程都有独立的一个ThreadLocalMap
 }
 //根据当前线程获取值(真正获取值的时候是根据ThreadLocal实例来获取的)
 public T get() {
     Thread t = Thread.currentThread();
     ThreadLocalMap map = getMap(t);
     if (map != null) {
         ThreadLocalMap.Entry e = map.getEntry(this);
         if (e != null) {
             @SuppressWarnings("unchecked")
             T result = (T)e.value;
             return result;
         }
     }
     return setInitialValue();  //获取的时候发现当前线程没有ThreadMap就会初始化一个
  }
  private T setInitialValue() {
       T value = initialValue();
       Thread t = Thread.currentThread();
       //为什还要获取一遍判断一遍?感觉不用呀
       ThreadLocalMap map = getMap(t);
       if (map != null)
           map.set(this, value);
       else
           createMap(t, value);
       return value;
  }

每个线程都有一个ThreadMap<ThreadLocal,value>,这样Thread可以拥有多个ThreadLocal
还有那个疑问暂时不知道为什么?

附带一个例子:每个线程维持自己的一个数据库连接

public class ConnectionFactory {
    private static ThreadLocal<Connection> connections = new ThreadLocal<Connection>();
    private static String URL = "jdbc:mysql://127.0.0.1:3306/xia";
    private static String USER = "root";
    private static String PASSWORD = "123";
    public static Connection getConnectionInstance() {
        System.out.println(Thread.currentThread().getName() + "获取Connection");
        Connection conn = connections.get();
        if (conn != null) {
            return conn;
        }
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(URL, USER, PASSWORD);
            connections.set(conn);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
}
public class ConnectionTest {
    public static void main(String[] args) {
        Connection conn_1 = ConnectionFactory .getConnectionInstance();
        Connection conn_2 = ConnectionFactory .getConnectionInstance();
        System.out.println(conn_1 == conn_2);
        new Thread(new Runnable() {
            Connection conn_3 = null;
            Connection conn_4 = null;

            @Override
            public void run() {
                conn_3 = ConnectionFactory .getConnectionInstance();
                conn_4 = ConnectionFactory .getConnectionInstance();
                System.out.println(conn_1 == conn_3);
                System.out.println(conn_3 == conn_4);
            }
        }).start();
    }
}

运行结果:

main获取Connection
Thu Jun 02 14:53:30 CST 2016 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
main获取Connection
true
Thread-0获取Connection
Thu Jun 02 14:53:30 CST 2016 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Thread-0获取Connection
false
true
版权声明:本文为博主原创文章,未经博主允许不得转载。

在web项目中使用 ThreadLocal 要谨慎,使用不当容易造成内存溢出

这里使用的servlet容器是 tomcat如果在web项目中,使用 ThreadLocal 不当,会造成 OutOfMemoryError。说明原因前 1:先讲一下 ThreadLocal,The...
  • liang_love_java
  • liang_love_java
  • 2016年09月29日 13:56
  • 2130

ThreadLocal 内部实现和应用场景

很多人都知道java中有ThreadLocal这个类,但是知道ThreadLocal这个类具体有什么作用,然后适用什么样的业务场景还是很少的。今天我就尝试以自己的理解,来讲解下ThreadLocal类...
  • z69183787
  • z69183787
  • 2016年05月24日 14:41
  • 6862

java ThreadLocal(应用场景及使用方式及原理)

Thread.java源码中: ThreadLocal.ThreadLocalMap threadLocals = null;即:每个Thread对象都有一个ThreadLocal.ThreadLoc...
  • qilixiang012
  • qilixiang012
  • 2014年07月30日 10:15
  • 5920

java 简单的ThreadLocal示例

  • 2013年03月24日 17:40
  • 6KB
  • 下载

java事务 - threadlocal

  • 2014年09月13日 12:46
  • 1.07MB
  • 下载

JAVA ThreadLocal类深入

  • 2011年07月31日 10:20
  • 47KB
  • 下载

【菜鸟学Java】14:使用ThreadLocal对Connection进行封装

问题背景:         使用JDBC进行开发的时候,每一次的增删改查都必须和数据库建立连接,才可以对数据项进行相应的操作。当我们的业务比较复杂的情况下,可能会出现在一个方法中多次的执行增删改查,...
  • u010929604
  • u010929604
  • 2016年02月24日 11:53
  • 1159

Java并发编程:深入剖析ThreadLocal

想必很多朋友对ThreadLocal并不陌生,今天我们就来一起探讨下ThreadLocal的使用方法和实现原理。首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码...
  • hb_peng
  • hb_peng
  • 2016年08月12日 10:17
  • 157

Java 并发编程深入学习——ThreadLocal 原理分析

介绍ThreadLocal 是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对于其他线程来说则无法获取到数据。应用场景在日常开发中用到...
  • ylyg050518
  • ylyg050518
  • 2017年04月25日 18:08
  • 282

Java线程的学习_ThreadLocal类

Java为线程安全提供了一些工具类,其中包括了ThreadLocal类。ThreadLocal类代表一个线程局部变量,通过把数据放在ThreadLocal中就可以让每个线程创建一个该变量的副本,从而避...
  • qq_35073878
  • qq_35073878
  • 2016年11月06日 16:54
  • 93
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java中ThreadLocal
举报原因:
原因补充:

(最多只允许输入30个字)