带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(10)

简介: 带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(10)

带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(9)https://developer.aliyun.com/article/1340060?groupCode=taobaotech


ThreadLocal原理

 

Thread 内部维护了一个 ThreadLocal.ThreadLocalMap 实例(threadLocals),ThreadLocal 的操作都是围绕threadLocals 来操作的。

 

image.pngthreadLocal.get()方法

 

 

 

1

/**

 

2

 

* Returns the value in the current thread's copy of this

3

 

* thread-local variable. If the variable has no value for the

4

 

* current thread, it is first initialized to the value returned

5

 

* by an invocation of the {@link #initialValue} method.

6

 

*

7

 

* @return the current thread's value of this thread-local

8

 

*/

 

public T get() {
// 1. 获取当前线程
Thread t = Thread.currentThread();
// 2. 获取当前线程内部的ThreadLocalMap变量t.threadLocals;
ThreadLocalMap map = getMap(t);
// 3. 判断map是否为null
if (map != null) {
// 4. 使用当前threadLocal变量获取entry
ThreadLocalMap.Entry e = map.getEntry(this);
// 5. 判断entry是否为null
if (e != null) {
// 6.返回Entry.value
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
  }
  }
// 7. 如果map/entry为null设置初始值
return setInitialValue(); 
}
  /**
* Variant of set() to establish initialValue. Used instead
* of set() in case user has overridden the set() method. 
*
  * @return the initial value 
  */
private T setInitialValue() {
// 1. 初始化value,如果重写就用重写后的value,默认null
T value = initialValue();
// 2. 获取当前线程
Thread t = Thread.currentThread();
// 3. 获取当前线程内部的ThreadLocalMap变量
ThreadLocalMap map = getMap(t);
if (map != null)
// 4. 不为null就set, key: threadLocal, value: value
map.set(this, value);
else
// 5. map若为null则创建ThreadLocalMap对象
createMap(t, value);
return value;
}
/**
*Create the map associated with a ThreadLocal. Overridden in
*InheritableThreadLocal.
*
*@param t the current thread
*@param firstValue value for the initial entry of the map
*/
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
/**
*Construct a new map initially containing (firstKey, firstValue).
*ThreadLocalMaps are constructed lazily, so we only create
*one when we have at least one entry to put in it.
*/
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
// 1. 初始化entry数组,size: 16
table = new Entry[INITIAL_CAPACITY];
// 2. 计算value的index
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
// 3. 在对应index位置赋值
table[i] = new Entry(firstKey, firstValue);
// 4. entry size size = 1;
// 5. 设置threshold: threshold = len * 2 / 3; setThreshold(INITIAL_CAPACITY);
}
/**
*Set the resize threshold to maintain at worst a 2/3 load factor.
*/
private void setThreshold(int len) { threshold = len * 2 / 3;
}

带你读《2022技术人的百宝黑皮书》——合理使用线程池以及线程变量(11)https://developer.aliyun.com/article/1340058?groupCode=taobaotech

相关文章
|
22天前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
100 38
|
20天前
|
Java
线程池内部机制:线程的保活与回收策略
【10月更文挑战第24天】 线程池是现代并发编程中管理线程资源的一种高效机制。它不仅能够复用线程,减少创建和销毁线程的开销,还能有效控制并发线程的数量,提高系统资源的利用率。本文将深入探讨线程池中线程的保活和回收机制,帮助你更好地理解和使用线程池。
44 2
|
22天前
|
Prometheus 监控 Cloud Native
JAVA线程池监控以及动态调整线程池
【10月更文挑战第22天】在 Java 中,线程池的监控和动态调整是非常重要的,它可以帮助我们更好地管理系统资源,提高应用的性能和稳定性。
58 4
|
22天前
|
Prometheus 监控 Cloud Native
在 Java 中,如何使用线程池监控以及动态调整线程池?
【10月更文挑战第22天】线程池的监控和动态调整是一项重要的任务,需要我们结合具体的应用场景和需求,选择合适的方法和策略,以确保线程池始终处于最优状态,提高系统的性能和稳定性。
90 2
|
1月前
|
Java 数据库连接 数据库
不同业务使用同一个线程池发生死锁的技术探讨
【10月更文挑战第6天】在并发编程中,线程池是一种常用的优化手段,用于管理和复用线程资源,减少线程的创建和销毁开销。然而,当多个不同业务场景共用同一个线程池时,可能会引发一系列并发问题,其中死锁就是最为严重的一种。本文将深入探讨不同业务使用同一个线程池发生死锁的原因、影响及解决方案,旨在帮助开发者避免此类陷阱,提升系统的稳定性和可靠性。
48 5
|
1月前
|
Dubbo Java 应用服务中间件
剖析Tomcat线程池与JDK线程池的区别和联系!
剖析Tomcat线程池与JDK线程池的区别和联系!
105 0
剖析Tomcat线程池与JDK线程池的区别和联系!
|
1月前
|
网络协议 安全 Java
难懂,误点!将多线程技术应用于Python的异步事件循环
难懂,误点!将多线程技术应用于Python的异步事件循环
61 0
|
1月前
|
设计模式 Java 物联网
【多线程-从零开始-玖】内核态,用户态,线程池的参数、使用方法详解
【多线程-从零开始-玖】内核态,用户态,线程池的参数、使用方法详解
58 0
|
1月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
43 1
C++ 多线程之初识多线程
|
24天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
19 3