面试大厂一定离不开的——ThreadLocal,它的实现原理你知道吗
} 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 方法都创建新的数据库连接会造成数据库的很大压力,这里可以有两种解决方案:
使用连接池管理连接,既不是每次都
创建、销毁连接,而是从一个连接池里借出可用的连接,用完将其归还。
可以看到,这里 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
内存模型图如下:
评论