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. linux下alias命令具体解释

    linux下alias命令具体解释 用途说明 设置命令的别名.在linux系统中假设命令太长又不符合用户的习惯,那么我们能够为它指定一个别名. 尽管能够为命令建立"链接" 解决长文 ...

  2. Microsoft Windows CE 5.0 Board Support Package, Boot Loader, and Kernel Startup Sequence

    Summary Learn about the initial, low-level startup sequence and the hardware platform functions that ...

  3. 动态代理3--Spring AOP分析

    Spring AOP的基本实现方式 ​Spring AOP,一种模块化机制,能够动态的对切点添加行为,而不破坏原有的代码结构. 这是一个非常好地动态代理的应用方式.Spring AOP实现依赖于JDK ...

  4. python安装了2.7之后终端无法使用退格,上下左右

    遇到RT问题,原因是由于在编译python的时候去烧readline库造成的 解决办法: yum install readline-devel 然后重新编译安装python,终端控制符可用!

  5. ios26--kvc

    // // main.m // 13-KVC的使用 // /** KVC: Key Value Coding(键值编码):1.取值赋值.2.字典转模型. */ #import <Foundati ...

  6. sql server 生成随机数 rand函数

    https://docs.microsoft.com/en-us/sql/t-sql/functions/rand-transact-sql?view=sql-server-2017 在某一个区间内生 ...

  7. oracle-扫盲贴:存储过程实现增删改查

    原文引入:http://blog.csdn.net/yangzhawen/article/details/8617179 oracle-扫盲贴:存储过程实现增删改查 分类: oracle2013-02 ...

  8. 学习MAP 地图好地址

    http://www.cnblogs.com/beniao/archive/2010/01/13/1646446.html Bēniaǒ成长笔记在IT江湖里我不是一名老手,我只是一名普通的程序员,愿意 ...

  9. dubbo作者讲编码原则

    刚看到梁飞谈到dubbo为保证代码质量开发人员必须要注意的,其实也是开发人员应该做的. 1. 防止空指针和下标越界 这是我最不喜欢看到的异常,尤其在核心框架中,我更愿看到信息详细的参数不合法异常, 这 ...

  10. TI BLE:SCAN

    主机会运行SCAN来搜寻广播中的设备 运行函数: GAPCentralRole_StartDiscovery( DEFAULT_DISCOVERY_MODE, DEFAULT_DISCOVERY_AC ...