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. 浅析分布式数据库中间件DDM

    前言 DDM是什么?这是华为云Paas推出的分布式数据库中间件,DDM(Distributed Database Middleware)是一个实现了Mysql协议栈的服务器,前端用户可以把它看做一个数 ...

  2. python 爬虫必知必会

    #python爬虫 #新闻数据 #机器学习:股票数据获取及分析 #网络搜索引擎的一个部件 #Http协议 #正则表达式 #多线程,分布式 #http报文展示 #Http 应答报文介绍 #1.应答码 # ...

  3. 图像处理之基础---基于opencv的灰度图像微分

    argv分别为,可执行文件名.读入的原始图像.输出原始图像的灰度值.输出原始图像灰度值沿x轴方向的一阶微分.输出原始图像灰度值沿x轴方向的二阶微分. #include #include #includ ...

  4. 【Android】使用 SwipeRefreshLayout 实现下拉刷新

    今天在codepath 上看到一个开源项目 [点击查看]使用到了 SwipeRefreshLayout 实现了下拉刷新,但演示样例并不完整,于是自己就动手写了下.之前看到郭霖的博客上也有介绍下拉刷新, ...

  5. DSPC6748中某问题的解决方式

    因为之前没有做过DSP相关的开发,属于菜鸟中的菜鸟.出现故障后.不知道从哪方面来解决这些小问题. 开发环境:CCS5.5.0 开发板:TI公司的TMS320C6748 问题: 控制台出现初始化结束后多 ...

  6. 用py文件调用操作系统的命名,粘包问题

    帅爆太阳的男人 1,执行代码 在py代码中去调用操作系统的命令 新的模块:subprocess, import subprocess r = subprocess().Popen( "dir ...

  7. 【bzoj4604】The kth maximum number

    暴力 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> ...

  8. 8-15 globalCompositeOperation阶段练习二

    8-15 globalCompositeOperation阶段练习二 <!DOCTYPE html> <html lang="zh-cn"> <hea ...

  9. BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP

    BZOJ_1584_[Usaco2009 Mar]Cleaning Up 打扫卫生_DP Description 有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= ...

  10. libnids TCP数据流重组,显示TCP连接过程的程序总无法捕获数据包解决办法:

      法一: 指定可用网卡: nids_params.device="lo"; 法二: nids.h中有这么一段: struct nids_chksum_ctl { u_int ne ...