ThreadLocal是什么?

  当使用ThreadLocal修饰变量的时候,ThreadLocal会为每个使用该变量的线程提供独立的变量副本,每个线程可以独立改变自己的副本,而不

影响其他线程的变量副本。

  相对于synchronized和lock实现对共享资源的操作互斥而实现原子性,这是一种新的思路解决并发问题。

原理:

public class Thread implements Runnable {
ThreadLocal.ThreadLocalMap threadLocals = null;
}
static class ThreadLocalMap {

        static class Entry extends WeakReference<ThreadLocal<?>> {
Object value; Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
} private static final int INITIAL_CAPACITY = 16; private Entry[] table; private int size = 0; private int threshold; // Default to 0 private void setThreshold(int len) {
threshold = len * 2 / 3;
} private static int nextIndex(int i, int len) {
return ((i + 1 < len) ? i + 1 : 0);
} private static int prevIndex(int i, int len) {
return ((i - 1 >= 0) ? i - 1 : len - 1);
}
}

ThreadLocalMap:

  ThreadLocal的内部类,类似Hashmap结构,以ThreadLocal为key,需要隔离的数据为value的Entry键值对数组结构。

  Entry继承了WeakReferences,只要发生GC,key为null的entry就会被清理掉

get()源码:

public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);//获取当前线程的ThreadLocalMap
if (map != null) {//如果不为空
ThreadLocalMap.Entry e = map.getEntry(this);//取出对应位置的Entry
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;//取出当前ThreadLocal对应的value值,返回
return result;
}
}
return setInitialValue();//如果没取到,进行初始化
}

getMap()源码:

ThreadLocalMap getMap(Thread t) {
return t.threadLocals;//获取线程的ThreadLocals,也就是ThreadLocal.ThreadLocalMap
}

setInitialValue()源码:

private T setInitialValue() {
T value = initialValue();//自定义初始化
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)//有对应的map,直接set
map.set(this, value);
else //否则创建新的map,保存当前线程内部
createMap(t, value);
return value;
}

set()源码:和前面一样

public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}

remove()源码:

public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
private void remove(ThreadLocal<?> key) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
if (e.get() == key) {
e.clear();
expungeStaleEntry(i);
return;
}
}
}

应用:

  数据库连接、Session管理、用户管理

public class UserContext {

    private static ThreadLocal<User> userHolder = new ThreadLocal<User>();

    public static void setUser(User user) {
userHolder.set(user);
} public static User getUser() {
return userHolder.get();
} }

下面两段代码来自:https://www.cnblogs.com/dolphin0520/p/3920407.html

public static ThreadLocal<Connection> connectionHolder = ThreadLocal.withInitial(() -> {
Connection conn = null;
try {
  conn = DriverManager.getConnection("", "", "");
} catch (SQLException e) {
  e.printStackTrace();
}
  return conn;
}); public static Connection getConnection() {
  return connectionHolder.get();
}
private static final ThreadLocal threadSession = new ThreadLocal();

public static Session getSession() throws InfrastructureException {
Session s = (Session) threadSession.get();
try {
if (s == null) {
s = getSessionFactory().openSession();
threadSession.set(s);
}
} catch (HibernateException ex) {
throw new InfrastructureException(ex);
}
return s;
}

与Thread同步机制的比较:

  ThreadLocal:用于线程间的数据隔离,适用于多实例对象的访问,并且这个对象很多地方都要用到

  Synchronized:用于线程间的数据共享

Spring中的应用:

  只有无状态的Bean才可以在多线程环境下共享,在Spring中,绝大部分Bean都可以声明为singleton作用域。就是因为Spring对一些Bean(

如RequestContextHolder、TransactionSynchronizationManager、LocaleContextHolder等)中非线程安全状态采用ThreadLocal进行处理,让

它们也成为线程安全的状态,因为有状态的Bean就可以在多线程中共享了。

并发和多线程(六)--ThreadLocal的更多相关文章

  1. python并发编程&多线程(二)

    前导理论知识见:python并发编程&多线程(一) 一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性 官网链 ...

  2. python并发编程&多线程(一)

    本篇理论居多,实际操作见:  python并发编程&多线程(二) 一 什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一 ...

  3. python多进程并发和多线程并发和协程

    为什么需要并发编程? 如果程序中包含I/O操作,程序会有很高的延迟,CPU会处于等待状态,这样会浪费系统资源,浪费时间 1.Python的并发编程分为多进程并发和多线程并发 多进程并发:运行多个独立的 ...

  4. Java多线程学习(一)---并发与多线程

    Java并发与多线程 摘要: 1. 并发与并行的区别,何为并发编程,并发编程的优势在哪 2. 多线程.多任务.多进程机制概述 3. 多线程.多任务.多进程机制与编程思想的关系 一.并发 1.1 并发与 ...

  5. 并发和多线程-八面玲珑的synchronized

    上篇<并发和多线程-说说面试常考平时少用的volatile>主要介绍的是volatile的可见性.原子性等特性,同时也通过一些实例简单与synchronized做了对比. 相比较volat ...

  6. C# 多线程六之Task(任务)三之任务工厂

    1.知识回顾,简要概述 前面两篇关于Task的随笔,C# 多线程五之Task(任务)一 和 C# 多线程六之Task(任务)二,介绍了关于Task的一些基本的用法,以及一些使用的要点,如果都看懂了,本 ...

  7. python高并发和多线程的关系

    “高并发和多线程”总是被一起提起,给人感觉两者好像相等,实则 高并发 ≠ 多线程 多线程是完成任务的一种方法,高并发是系统运行的一种状态,通过多线程有助于系统承受高并发状态的实现.   高并发是一种系 ...

  8. php-fpm和cgi,并发响应的理解以及高并发和多线程的关系

    首先搞清楚php-fpm与cgi的关系 cgi cgi是一个web server与cgi程序(这里可以理解为是php解释器)之间进行数据传输的协议,保证了传递的是标准数据. php-cgi php-c ...

  9. Java并发和多线程:序

      近期,和不少公司的"大牛"聊了聊,当中非常多是关于"并发和多线程"."系统架构"."分布式"等方面内容的.不少问题, ...

随机推荐

  1. 运行shell脚本报错 &#39;\357\273\277&#39;: command not found 解决的方法

    1,删除BOM,在vi以下运行以下的命令就可以 :set nobomb 2,原因: 所谓BOM,全称是Byte Order Mark.它是一个Unicode字符,通常出如今文本的开头,用来标识字节序( ...

  2. MySQL-数据更新(UPDATE)

    MySQL-UPDATE语句 功能介绍:用于更新表中的现有数据.亦可用UPDATE语句来更改表中单个行,一组行或所有行的列值. MySQL-UPDATE语法: UPDATE [LOW_PRIORITY ...

  3. ios Enum Value To NSString

    #define enumToString(value)  @#value eg. typedef NS_ENUM(NSInteger, Sex) { Male = 0, Famale = 1, }; ...

  4. HDU 5428 分解质因数

                                                                                                   The F ...

  5. 阳性比例 mysql CASE UNION ALL

    阳性比例 mysql CASE UNION ALL SELECT t.*,t.type_0/all_ FROM ( SELECT FROM_UNIXTIME(create_time,'%Y-%m-%d ...

  6. android studio 使用

    java5-7适用android,java8对安卓支持不好. mac osx 需要安装jdk8, google Nexus模拟器, Intellij是JetBrains发布的. Intellij有2个 ...

  7. SQLyog软件里无法插入中文(即由默认的latin1改成UTF8编码格式)

    问题详情: 无法插入中文? 解决办法: 需要修改编码格式,由默认的latin1改为utf8. 改成, 成功!

  8. android 3G移植【转】

    本文转载自:http://blog.csdn.net/hanmengaidudu/article/details/17028383 一 开发环境简介 内容 说明 3G模块 华为EM820W(WCDMA ...

  9. 【HDU4706】Children's Day

    http://acm.hdu.edu.cn/showproblem.php?pid=4706 水题,也不知道有没有spj // <4706.cpp> - 11/03/16 14:11:21 ...

  10. 【Dairy】2016.10.20 生日记

    今天又有人生日耶(朱子鸿)~破壳快乐! 遥犇献歌一曲<就是现在>掌声!!!!!! 开森,呲到了草莓蛋糕,很好呲的.. 然后下去跑步,拿着奶油叉子,往卜卜脸上抹,可惜zks吸引不够(坑队友) ...