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. 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习

    反射实现Model修改前后的内容对比   在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...

  2. Hiho1041 国庆出游 搜索题解

    题目3 : 国庆出游 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描写叙述 小Hi和小Ho准备国庆期间去A国旅游.A国的城际交通比較有特色:它共同拥有n座城市(编号1-n): ...

  3. js全局替换空格,制表符,换行符

    this.value = this.value.replace(/\s+/g,'') "/ "这个是固定写法, "\s"匹配任何不可见字符,包括空格.制表符.换 ...

  4. JavaScript基础 -- DOM

    一.DOM全称 文档对象模型(Document Object Model) 二.DOM是什么 DOM可以说是制作动态页面的强有力工具.DOM不是JavaScript语言的一部分,而是内置在浏览器中的一 ...

  5. Codeforces Round #319 (Div. 2) C. Vasya and Petya's Game 数学题

                                                     C. Vasya and Petya's Game                           ...

  6. C语言8大经典排序算法(1)

    算法一直是编程的基础,而排序算法是学习算法的开始,排序也是数据处理的重要内容.所谓排序是指将一个无序列整理成按非递减顺序排列的有序序列.排列的方法有很多,根据待排序序列的规模以及对数据的处理的要求,可 ...

  7. 同一个站点下,兼容不同版本的JQuery

    https://stackoverflow.com/questions/1566595/can-i-use-multiple-versions-of-jquery-on-the-same-page Y ...

  8. Unicode and .NET

    http://csharpindepth.com/Articles/General/Unicode.aspx Scope of this page This is a big topic. Don't ...

  9. lucene .doc里存储的skiplist跳表

    http://forfuture1978.iteye.com/blog/546841 见图: lucene-6.5.1-src/lucene-6.5.1$ grep "skiplistwri ...

  10. POJ2352 star

    传送门 这道题有个非常好听的名字,求二维偏序! 听起来似乎很高端,但就是让求满足对于每个i,xi < xj && yi < yj的个数. 这道题特别良心,给的顺序都是y递增 ...