ThreadLocal 原理
程序员文章站
2022-06-01 17:53:28
...
由于Alibaba面试官提到ThreadLoacl,但是由于之前根本没有使用过,也没真正的去专研这个类。连夜赶出一篇文章。
ThreadLocal
ThreadLocal是解决多线程访问同一变量,保证线程安全产生的。它为每一个使用变量的线程提供一个独立的副本。换句话说,每个线程都持有一个该对象的副本。自己对自己的副本进行操作就不会出现线程不安全的问题。它将每个线程和对象的副本存放在ThreadLocalMap(ThreadLocal的一个静态内部类)中,ThreadLocalMap下面是一个Entry[]数组。
在创建ThreadLocal时,ThreadLocalMap内是空的,当调用get()/set()方法时,就会对其中的ThreadLocalMap获取/添加操作。
例子:
package com.example.demo.juc;
/**
* ThreadLocalTest
* @author Logan
*/
public class ThreadLocalTest {
// long Thread Local
private ThreadLocal<Long> longLocal = new ThreadLocal<Long>();
// string Thread Local
private ThreadLocal<String> stringLocal = new ThreadLocal<String>();
public static void main(String[] args) throws InterruptedException {
final ThreadLocalTest threadLocalTest = new ThreadLocalTest();
// 设置值
threadLocalTest.set();
System.out.println("===1===");
System.out.println(threadLocalTest.getLongLocal().get());
System.out.println(threadLocalTest.getStringLocal().get());
// 创建线程
Thread thread = new Thread(()->{
// 当这里调用了set方法,进一步调用了ThreadLocal的set方法是,
// 会将ThreadLocal变量存储到该线程的ThreadLocalMap类型的成员变量threadLocals中,
// 注意的是这个threadLocals变量是Thread线程的一个变量,而不是ThreadLocal类的变量。
threadLocalTest.set();
System.out.println("===2===");
System.out.println(threadLocalTest.getLongLocal().get());
System.out.println(threadLocalTest.getStringLocal().get());
});
thread.start();
thread.join();// 强行加入
System.out.println("===3===");
System.out.println(threadLocalTest.getLongLocal().get());
System.out.println(threadLocalTest.getStringLocal().get());
}
/**
* 设置线程的Id 和 Name
*/
private void set() {
longLocal.set(Thread.currentThread().getId());
stringLocal.set(Thread.currentThread().getName());
}
public ThreadLocal<Long> getLongLocal() {
return longLocal;
}
public ThreadLocal<String> getStringLocal() {
return stringLocal;
}
}
ThreadLocal 的应用场景
1.获取数据库连接。
class DBTest {
private final static String DB_URL = "url";
private static ThreadLocal<Connection> connectionThreadLocal = new ThreadLocal<Connection>(){
@Override
protected Connection initialValue() {
try {
Connection connection = DriverManager.getConnection(DB_URL);
connectionThreadLocal.set(connection);
return connection;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
};
private static Connection getConnect(){
return connectionThreadLocal.get();
}
}
2.Session的管理
class SessionTest{
private static ThreadLocal sessionThreadLocal = new ThreadLocal();
public static Session getSession() {
Session session = (Session) sessionThreadLocal.get();
if(session == null){
session = getSessionFactory().openSession();
}
return session;
}
}
All in All : ThreadLocal是为了保证线程安全的,但是需要复制大量的副本,这也不是一个好事,增大的内存的开销。
线程安全还可以使用ConcurrentHashMap、ConcurrentSkipListMap、CopyOnWriteArrayList等容器,也可以保证线程安全。
上一篇: ThreadLocal原理
推荐阅读
-
关于APP第三方登录与服务器通讯,求原理
-
html页面渲染的原理及优化_html/css_WEB-ITnose
-
SQL语句执行过程原理讲解
-
单点登录 Ucenter 原理分析
-
Mybatis源码分析——运行原理及流程
-
MySQL中Join算法实现原理分析[组图]_MySQL
-
PHP Curl多线程原理实例详解_PHP教程
-
Android的线程通信:消息机制原理(Message,Handler,MessageQueue,Looper),异步任务AsyncTask,使用JSON
-
理解Javascript_05_原型继承原理_javascript技巧
-
php图片加水印原理(超简单的实例代码)_php技巧