threadlocal

Hystrix 跨线程共享变量

假装没事ソ 提交于 2019-11-28 23:06:29
1.在 Servlet 容器线程与 Hystrix 线程中共享变量的问题 今天遇到一个问题,在使用 zuul 的过程中我想要在 Hystrix 执行的线程中获取到 com.netflix.zuul.context.RequestContext 中的数据。不过 RequestContext 是基于 ThreadLocal 的,所以在 Hystrix 执行的线程中调用 com.netflix.zuul.context.RequestContext#getCurrentContext 函数获取到的只能是一个空的没有任何数据的 RequestContext 对象。因为 Hystrix 默认是在另一个线程中执行的 , 而 zuul filter 则是在 servlet 容器的线程中执行的,基于 ThreadLocal 的 RequestContext 自然无法起作用了。 2.在 Servlet 容器线程与 Hystrix 线程中共享变量的实现方式 2.1 关键类介绍 Hystrix 的设计者们早就考虑到了这个问题,并且提供了解决方案。关键类是 : com.netflix.hystrix.strategy.concurrency.HystrixRequestContext ,com.netflix.hystrix.strategy.concurrency

多线程编程学习总结

梦想的初衷 提交于 2019-11-28 21:57:10
线程的概念和原理 为什么使用多线程? 为了更高效的完成任务和利用CPU资源,现在的操作系统设计为多任务操作系统,而多进程和多线程是实现多任务的方式。 什么是进程和线程? 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。进程是OS分配资源的最小单位。 线程是指进程中的一个执行流程,一个进程中可以运行多个线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。进程是OS调度的最小单位。 工作原理? 多线程是这样一种机制,它允许在程序中并发执行多个指令流,每个指令流都称为一个线程,彼此间互相独立。线程又称为轻量级进程,它和进程一样拥有独立的执行控制,由操作系统负责调度,区别在于线程没有独立的存储空间,而是和所属进程中的其它线程共享一个存储空间,这使得线程间的通信远较进程简单。 具体到java内存模型,由于Java被设计为跨平台的语言,在内存管理上,显然也要有一个统一的模型。系统存在一个主内存(Main Memory), Java中所有变量都储存在主存中,对于所有线程都是共享的。每条线程都有自己的工作内存(Working Memory)——调用栈,工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。 多个线程的执行是并发的,也就是在逻辑上“同时”

JDK ThreadLocal解析

社会主义新天地 提交于 2019-11-28 20:41:21
Java ThreadLocal解析 ThreadLocal 线程本地变量, 线程私有, 在 Thread 类中用 ThreadLocal.ThreadLocalMap threadLocals 以数组的形式存储. 因为是线程私有的变量, 所以不会有多线程访问的线程安全问题, 下面就对它开始解析(JDK1.8 的 ThreadLocal). threadLocalHashCode 在说 ThreadLocal 的使用之前, 先说一个比较重要的东西, 就是 threadLocalHashCode , 这个hashCode 的值用来计算 当前 ThreadLocal 应当位于 ThreadLocalMap 的数组中的下标 , 为什么是 应当 呢, 请往下看 // ThreadLocalHashCode 递增值 private static final int HASH_INCREMENT = 0x61c88647; /** * Returns the next hash code. */ private static int nextHashCode() { return nextHashCode.getAndAdd(HASH_INCREMENT); } // 每个 ThreadLocal 的 threadLocalHashCode 通过一个静态的原子变量递增而获得 private

ThreadLocal解析

牧云@^-^@ 提交于 2019-11-28 20:38:11
  ThreadLocal为解决多线程程序的并发问题提供了一种新的思路。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。从线程的角度看,目标变量就象是线程的本地变量,这也是类名中“Local”所要表达的意思。   ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不同的变量值完成操作的场景。 ThreadLocal的内部结构图: 每个Thread线程内部都有一个Map。 Map里面存储线程本地对象(key)和线程的变量副本(value) 但是,Thread内部的Map是由ThreadLocal维护的,由ThreadLocal负责向map获取和设置线程的变量值。   所以对于不同的线程,每次获取副本值时,别的线程并不能获取到当前线程的副本值,形成了副本的隔离,互不干扰。 【问题】ThreadLocal是如何做到为每一个线程维护变量的副本的呢?   答:在ThreadLocal类中有一个Map,用于存储每一个线程的变量副本,Map中元素的键为线程对象,而值对应线程的变量副本。

谈谈ThreadLocal

故事扮演 提交于 2019-11-28 18:48:38
谈谈ThreadLocal ThreadLocal,即线程局部变量,它被设计用来解决变量共享的线程安全问题。线程安全问题发生的根本原因在于 多个线程会对同一个临界区资源进行操作 。Synchonized和ThreadLocal是两种不同的解决多线程并发访问的方式。Synchonized使用了锁机制,使得同一时间只有一个线程能访问变量,而ThreadLocal是为每一个线程拷贝变量的副本,隔离了多个线程对数据的共享。所以,Synchronized用于线程间的数据共享,ThreadLocal用于线程间的数据隔离。在开发中如果遇到在一个线程中一些数据在不同层次的代码中需要通过参数来回传递,但是不想增加性能损耗的问题时,最好使用ThreadLocal来解决这样的安全问题。从根本上看,其实使用ThreadLocal是一种“空间换时间”的方案。 引用类型 为了理解ThreadLocal的实现原理,首先需要了解引用类型的概念。根据引用类型语义的强弱,可以把引用分为四种类型。分别为强引用、软引用、弱引用和虚引用,它们的强弱关系依次递减。 引用类型 使用方式 回收时间 强引用 A a = new A(); 强引用指向的对象不会被GC回收 软引用 SoftReserence a = new SoftReference<>(t); OOM之前会被回收 弱引用 WeakReference a = new

并发下常用关键字的原理

风流意气都作罢 提交于 2019-11-28 17:25:20
对Synchronized的理解 synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。 另外,在 Java 早期版本中,synchronized属于重量级锁,效率低下,因为监视器锁(monitor)是依赖于底层的操作系统的 Mutex Lock 来实现的,Java 的线程是映射到操作系统的原生线程之上的。如果要挂起或者唤醒一个线程,都需要操作系统帮忙完成,而操作系统实现线程之间的切换时需要从用户态转换到内核态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高,这也是为什么早期的 synchronized 效率低的原因。在 Java 6 之后 Java 官方对从 JVM 层面对synchronized 较大优化,所以现在的 synchronized 锁效率也优化得很不错了。JDK1.6对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。 synchronized关键字最主要的三种使用方式: 修饰实例方法: 作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁 修饰静态方法: :也就是给当前类加锁,会作用于类的所有对象实例,因为静态成员不属于任何一个实例对象,是类成员( static

ThreadLocal

依然范特西╮ 提交于 2019-11-28 15:47:44
import java.util.Random; /** * ThreadLocal类及应用技巧 * ******************************************************************* * 每个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map中增加一条记录,key * 分别是各自的线程,values是各自的set方法穿进去的值。在线程结束时可以调用ThreadLocal.clear(); * 方法,这样会更快释放内存,不调用也可以,因为线程结束后也可以自动释放相关的ThreadLocal变量。 * 实现对ThreadLocal变量的封装,让外界不要直接操作ThreadLocal变量 * 对基本类型的数据的封装,这种应用相对少见。 * 对对象类型的数据的封装,比较常见,即让某个类针对不同线程分别创建一个独立的实例对象。 * 总结: * 一个ThreadLocal代表一个变量,故其中里只能放一个数据,你有两个变量都要线程范围内 * 共享,则要定义两个ThreadLocal对象。如果有一百个变量要线程共享呢?把ThreadLocal封装 * 到一个单例类中。 * * Struts2中的思想就是ThreadLocal模式 * * *****************************************

Java 8 ThreadLocal 源码解析

风格不统一 提交于 2019-11-28 13:47:30
概述 ThreadLocal是一个本地线程副本变量工具类,很多地方称作线程本地变量,也有些地方称作线程本地存储。其原理就是为每个线程都提供一个副本变量,使得这些变量是线程级别的、私有的变量。所以对于不同的线程,每次获取副本值时,别的线程并不能获取到当前线程的副本值,形成了对副本的隔离,使得各个线程之间互不影响,从而在高并发场景下实现无状态的调用,特别适用于各个线程依赖不通的变量值完成操作的场景。如为每个线程创建一个独立的数据库连接。 我们来看一个并发问题:当一个可变对象被多个线程访问时,可能会得到非预期的结果。例如,在《 避免创建不必要的对象 》一文中,DateUtils 的两个方法 format(Date date)和parse(String strDate)都是非线程安全的,它们在格式化日期的时候,共享从父类 DateFormat 继承而来的 Calendar 对象。为了解决这个并发问题,文中给出了一种基于ThreadLocal的解决方案,本文在此基础上,从源码的角度分析ThreadLocal是怎么实现线程安全的,所用java.version为1.8.0_05。 ThreadLocal get 源码解读 在使用 ThreadLocal 时,当前线程通过 get() 方法访问 ThreadLocal 中包含的变量。 /** * Returns the value in the

Spring单例与线程安全小结

时光毁灭记忆、已成空白 提交于 2019-11-28 10:32:34
一、Spring单例模式与线程安全 Spring框架里的bean,或者说组件,获取实例的时候都是默认的单例模式,这是在多线程开发的时候要尤其注意的地方。 单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。 当多用户同时请求一个服务时,容器会给每一个请求分配一个线程,这是多个线程会并发执行该请求多对应的业务逻辑(成员方法),此时就要注意了,如果该处理逻辑中有对该单列状态的修改(体现为该单列的成员属性),则必须考虑线程同步问题 同步机制的比较  ThreadLocal和线程同步机制相比有什么优势呢?ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。   在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。   而ThreadLocal则从另一个角度来解决多线程的并发访问。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时

父线程与子线程传值问题

泪湿孤枕 提交于 2019-11-28 10:24:07
一、ThreadLocal回顾 ThreadLocal对象用于在同一个线程中传递数据,避免显式的在方法中传参。 每个线程中保存了ThreadLocalMap对象,ThreadLocalMap对象的key就是ThreadLocal对象本身,value就是当前线程的值。 看下ThreadLocal的get方法 public T get() { //当前线程 Thread t = Thread.currentThread(); //获取当前线程的ThreadLocalMap对象 ThreadLocalMap map = getMap(t); if (map != null) { //获取该ThreadLocal对象的value ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } //设置初始值 return setInitialValue(); } //获取当前线程的ThreadLocalMap对象 ThreadLocalMap getMap(Thread t) { return t.threadLocals; } View Code