- 浏览: 81513 次
-
文章分类
最新评论
-
kevinflynn:
...
ThreadLocal 源码分析 -
kevinflynn:
[url=aaaa][/url]
ThreadLocal 源码分析 -
kevinflynn:
学习到了 感谢楼主。
ThreadLocal 源码分析
/*
* Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package com.hanlin.fadp;
import java.lang.ref.*;
/**
* This class extends <tt>ThreadLocal</tt> to provide inheritance of values
* from parent thread to child thread: when a child thread is created, the
* child receives initial values for all inheritable thread-local variables
* for which the parent has values. Normally the child's values will be
* identical to the parent's; however, the child's value can be made an
* arbitrary function of the parent's by overriding the <tt>childValue</tt>
* method in this class.
*
* <p>Inheritable thread-local variables are used in preference to
* ordinary thread-local variables when the per-thread-attribute being
* maintained in the variable (e.g., User ID, Transaction ID) must be
* automatically transmitted to any child threads that are created.
*
* @author Josh Bloch and Doug Lea
* @see ThreadLocal
* @since 1.2
*/
public class InheritableThreadLocal<T> extends ThreadLocal<T> {
/**
* 这个方法留给子类实现
*
* @param parentValue the parent thread's value
* @return the child thread's initial value
*/
protected T childValue(T parentValue) {
return parentValue;
}
/**
* 重写getMap方法,返回的是Thread的inheritableThreadLocals引用
*
* @param t the current thread
*/
ThreadLocalMap getMap(Thread t) {
return t.inheritableThreadLocals;
}
/**
* 重写createMap方法,构造的ThreadLocalMap会传给Thread的inheritableThreadLocals 变量
*
* @param t the current thread
* @param firstValue value for the initial entry of the table.
* @param map the map to store.
*/
void createMap(Thread t, T firstValue) {
t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
}
}
它是如何实现父子线程间 ThreadLocal 传递的了?
首先,重写了 getMap 和 createMap 方法,因为 ThreadLocal 在执行 set 方法或者 get 方法的时候,会用到.
是不是发现了啥?这里使用的是 inheritableThreadLocals,而不再是 ThreadLocal 中的 threadLocals.
再看 Thread 类的 init 方法:
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name.toCharArray();
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();
/*
* Do we have the required permissions?
*/
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
// 这里 inheritableThreadLocals 将不再为空,ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); 语句会把父类中的 ThreadLocal 中的值拷贝一份到子类中.
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
tid = nextThreadID();
}
说明:父子线程 ThreadLocal 在拷贝的时候,拷贝的是引用,也就是说如果父线程修改了 ThreadLocal 中的某个对象,那么子线程中 ThreadLocal 的值也会跟着变.
理论分析:
测试:
package com.hanlin.fadp;
public class InheritableThreadLocalTest {
static class Person{
String name;
public Person(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
public static ThreadLocal<Person> inheritableThreadLocal = new InheritableThreadLocal<Person>();
static CountDownLatch latch = new CountDownLatch(1);
public static void main(String args[]) throws InterruptedException {
Person tom = new Person("tom");
inheritableThreadLocal.set(tom);
new Thread(new Runnable() {
@Override
public void run() {
try {
Person p = inheritableThreadLocal.get();
p.setName("sdsds");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程<InheritableThreadLocal>:" + inheritableThreadLocal.get());
latch.countDown();
}
}, "AAAAA").start();
System.out.println("父线程<InheritableThreadLocal>:" + inheritableThreadLocal.get());
Thread.sleep(1000);
// Person p = inheritableThreadLocal.get();
// p.setName("sdsds");
// inheritableThreadLocal.set(p);
latch.await();
System.out.println("父线程<InheritableThreadLocal>:" + inheritableThreadLocal.get());
}
}
结果:
发表评论
-
AtomicInteger 源码分析
2019-01-24 16:11 1026AtomicInteger 是如何实现原子操作的了? 答案是 ... -
SynchronousQueue 源码初步分析
2019-01-23 16:56 1258简介: 就是一个 put 操作必须和 take 操作对应. 如 ... -
LinkedBlockingDeque 源码分析
2019-01-22 16:44 1516简介: LinkedBlockingDeque 是一个双端队 ... -
CopyOnWriteArrayList 源码分析
2019-01-19 16:02 1387简介: 写操作时上锁,然后拷贝一个新的数组,操作新数组,将当 ... -
CyclicBarrier 源码分析
2019-01-19 13:55 1537简介: CyclicBarrier 实现这么一个功能,比如说吃 ... -
Semaphore 源码分析
2019-01-18 17:53 1426介绍: Semaphore 用于对某一物理或逻辑资源被同一时间 ... -
ThreadPoolExecutor 源码分析
2019-01-16 11:10 2144首先说明的是,这个和 ReadWriteLock 一样,同样是 ... -
分析 Java 任务的执行
2019-01-13 20:26 2080Java 并发中会大量使用到多线程,那么Java是如何使用多线 ... -
BlockingQueue 源码分析
2019-01-13 20:19 1354public interface BlockingQueue& ... -
LinkedBlockingQueue源码分析
2019-01-13 20:16 673LinkedBlockingQueue 其实实现的是一个生产者 ... -
FutureTask WaitNode 源码分析
2019-01-11 17:24 1985waiter 存放等待的线程,这是一个单链表,没有用 lock ... -
关于 Future 类 boolean cancel(boolean mayInterruptIfRunning) 的疑问
2019-01-11 09:07 0boolean cancel(boolean mayInter ... -
关于 Future 类 boolean cancel(boolean mayInterruptIfRunning) 的疑问
2019-01-10 21:05 2429boolean cancel(boolean mayInter ... -
ThreadLocal 源码分析
2019-01-05 16:18 2374说明: 每个线程内部持有一个 ThreadLocalMap ... -
ReentrantReadWriteLock 简介
2019-01-04 15:54 14571.首先说明 ReentrantReadWriteLock 和 ... -
CountDownLatch 源码分析
2019-01-03 18:31 1119思路分析: CountDownLatch 的思路是:首先申 ... -
ConditionObject 类分析
2018-12-24 14:28 660Condition 实现主要通过两个方法. ① await ...
相关推荐
* InheritableThreadLocal 的实现原理和源码分析 * InheritableThreadLocal 与 ThreadLocal 的区别 * 使用 InheritableThreadLocal 需要注意的线程安全问题 * InheritableThreadLocal 在多线程编程中的应用场景和...
### Java进阶知识点详解 #### 第一章:基本语法 ##### 关键字 - **static**:用于定义...以上是对Java进阶知识点的详细解析,覆盖了基本语法、JDK源码分析等多个方面,有助于深入理解Java语言的核心机制及高级特性。
`SecurityContextHolder` 类提供了获取和设置安全上下文的方法,通常通过 `SecurityContextHolder.MODE_INHERITABLETHREADLOCAL` 模式在多线程环境中传播。 **6. ** **用户详情服务(UserDetailsService)** 用户...
scratch少儿编程逻辑思维游戏源码-上下飞行.zip
kkzhilu_Code-Generate_32152_1745864907745
艺术博客_SpringSpringMVCMybatisShirojQueryBootstrapechartswebuploaderlayui_博客管理图表数据日
scratch少儿编程逻辑思维游戏源码-面具古墓.zip
scratch少儿编程逻辑思维游戏源码-时钟上的冰块.zip
健康监测_Android开发_BLE蓝牙通信_心率数据采集与存储_基于小米手环2的实时心率监测应用_支持后台长时间运行的心率记录工具_可导出SQLite数据库的心率数据分析系统_适
scratch少儿编程逻辑思维游戏源码-梦魇忍者.zip
scratch少儿编程逻辑思维游戏源码-谁建得更高.zip
scratch少儿编程逻辑思维游戏源码-忍者攀登.zip
模拟端 后端 qt前端
数据可视化_Android原生Canvas绘图_3D与非3D柱形图饼图折线图面积图曲线图环形图玫瑰图雷达图散点图气泡图仪表盘刻度盘漏斗图象限图_支持手势缩放滑动交互多图叠加动画效果
scratch少儿编程逻辑思维游戏源码-米克 demo.zip
聚合支付系统/官方个人免签系统/三方支付系统稳定安全高并发 附教程 系统采用FastAdmin框架独立全新开发,安全稳定,系统支持代理、商户、码商等业务逻辑。 针对最近一些JD,TB等业务定制,子账号业务逻辑API 非常详细,方便内置对接! IP白名单 业务逻辑 支持IP白名单,黑名单,全局白名单,全局黑名单,保障系统的安全。 接口验签名 采用支付宝RSA加密接口方式,防止篡改数据,导致对账困难,资金大量损失,无故少钱 对接灵活 全部对接参数灵活操作 风控完善 轮询、交易金额、随机金额、最大金额、最小金额等 测试环境: Nginx+PHP7.0+MySQL5.6 网站运行目录:/public 伪静态设置为:thinkphp规则 数据库信息修改路径:/application/database.php
第一步 package.json 下载这三个包 shelljs :执行 shell命令 ssh2-sftp-client 与服务器建立链接(内部有ssh2) chalk 打印彩色输出 第二步 配置脚本命令 deploy 注意后边加上运行环境 执行deploy命令时内部执行了打包动作 「 "deploy": "node deploy/index.js --prod」 第三步准备服务器密码 账号 部署地址 备份地址等等 参考如下 放到 config.js 中 module.exports = [ { id: 0, nodeEnv: "prod", name: "正式环境", domain: "", host: "ip", port: 端口, username: "用户名", password: "密码", path: "/data/www/paccount",//部署路径 removepath: "/data/www/paccount", //删除路径 }, ]; 第四步 如果需要在服务器执行命令 在部署完成后执行 chmodDir 自行决定
scratch少儿编程逻辑思维游戏源码-恐怖矿井.zip
scratch少儿编程逻辑思维游戏源码-爬墙鸟.zip
scratch少儿编程逻辑思维游戏源码-亮灯.zip