写点什么

面试大厂一定离不开的——ThreadLocal,它的实现原理你知道吗

  • 2021 年 11 月 12 日
  • 本文字数:1465 字

    阅读完需:约 5 分钟

} catch (SQLException e) {


e.printStackTrace();


}


}


return connect;


}


public void closeConnection() {


if(connect!=null) {


try {


connect.close();


} catch (SQLException e) {


e.printStackTrace();


}


}


}


}


class ConnectionManagerTest {


private String url = System.getProperty("URL");


public void insert() {


ConnectionManager connectionManager = new ConnectionManager();


Connection connection = connectionManager.openConnection(this.url);


//使用 connection 进行操作


connectionManager.closeConnection();


}


public void update() {


ConnectionManager connectionManager = new ConnectionManager();


Connection connection = connectionManager.openConnection(this.url);


//使用 connection 进行操作


connectionManager.closeConnection();


}


}


每个 CURD 方法都创建新的数据库连接会造成数据库的很大压力,这里可以有两种解决方案:


  1. 使用连接池管理连接,既不是每次都


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


创建、销毁连接,而是从一个连接池里借出可用的连接,用完将其归还。


  1. 可以看到,这里 connection 的建立最好是这样的:每个线程希望有自己独立的连接来避免同步问题,在线程内部希望共用同一个连接来降低数据库的压力,那么使用 ThreadLocal 来管理数据库连接就是最好的选择了。它为每个线程维护了一个自己的连接,并且可以在线程内共享。


class ConnectionManager {


private static String url = System.getProperty("URL");


private static ThreadLocalconnectionHolder = ThreadLocal.withInitial(() -> {


try {


return DriverManager.getConnection(url);


} catch (SQLException e) {


e.printStackTrace();


}


return null;


});


public static Connection openConnection() {


return connectionHolder.get();


}


public static void closeConnection() {


Connection connect = connectionHolder.get();


if(connect!=null) {


try {


connect.close();


} catch (SQLException e) {


e.printStackTrace();


}


}


}


}


另外还可以用到其他需要每个线程管理一份自己的资源副本的地方:An Introduction to ThreadLocal in Java

实现原理

这里面涉及到三种对象的映射:Thread-ThreadLocal 对象-ThreadLocal 中存的具体内容,既然是每个线程都会有一个资源副本,那么这个从 ThreadLocal 对象到存储内容的映射自然就会存在 Thread 对象里:


ThreadLocal.ThreadLocalMap threadLocals = null;


而 ThreadLocal 类只是提供了访问这个 Map 的接口:


public T get() {


Thread t = Thread.currentThread();


ThreadLocalMap map = getMap(t);


if (map != null) {


ThreadLocalMap.Entry e = map.getEntry(this);


if (e != null) {


@SuppressWarnings("unchecked")


T result = (T)e.value;


return result;


}


}


return setInitialValue();


}


public void set(T value) {


Thread t = Thread.currentThread();


ThreadLocalMap map = getMap(t);


if (map != null)


map.set(this, value);


else


createMap(t, value);


}


这个 ThreadLocalMap 是 ThreadLocal 的内部类,实现了一个类似 HashMap 的功能,其内部维护了一个 Entry 数组,下标就是通过 ThreadLocal 对象的 threadLocalHashCode 计算得来。这个 Entry 继承自 WeakReference,实现对 key,也就是 ThreadLocal 的弱引用:


static class Entry extends WeakReference<threadlocal


/** The value associated with this ThreadLocal. */


Object value;


Entry(ThreadLocal k, Object v) {


super(k);


value = v;


}


}


</threadlocal


内存模型图如下:

评论

发布
暂无评论
面试大厂一定离不开的——ThreadLocal,它的实现原理你知道吗