03ThreadLocal篇(D1_ThreadLocal)

目录

一、学习前言

二、认识ThreadLocal

三、与Synchronized的区别

四、基本使用

五、从源码层次理解原理

1. set

2. get

3. remove

六、与Thread,ThreadLocalMap之间的关系

七、使用场景

场景一:存储用户Session

场景二:数据库连接,处理数据库事务

场景三:数据跨层传递(controller,service, dao)

场景四:Spring使用ThreadLocal解决线程安全问题

八、内存泄漏问题

1. 是否会有内存泄漏?

2. 怎么解决这个内存泄漏问题


一、学习前言

多线程访问同一个共享变量时特别容易出现并发问题,特别是在多个线程需要对一个共享变量进行

写入时。

为了保证线程安全,一般使用者在访问共享变量时需要进行适当的同步,如图。

同步的措施一般是加锁,这就需要使用者对锁有一定的了解,这显然加重了使用者的负担。

那么有没有一种方式可以做到,当创建一个变量后,每个线程对其进行访问的时候,访问的是自己

线程的变量呢?

其实 ThreadLocal 就可以做这件事情,虽然 ThreadLocal 并不是为了解决这个问题而出现的。

ThreadLocal 是 JDK 包提供的,它提供了线程本地变量,也就是如果你创建了一个 ThreadLocal

变量,那么访问这个变量的每个线程都会有这个变量的一个本地副本。

当多个线程操作这个变量时,实际操作的是自己本地内存里面的变量,从而避免了线程安全问题。

创建一个 ThreadLocal 变量后,每个线程都会复制一个变量到自己的本地内存,如图所示。

二、认识ThreadLocal

ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而

言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了

一个副本,那么每个线程可以访问自己内部的副本变量。

ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不

同的副本。

这里有几点需要注意:

  • 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。

这也是 ThreadLocal 命名的由来。

  • 既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题。

ThreadLocal 提供了线程本地的实例。

它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。

ThreadLocal 变量通常被private static修饰。

当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。

总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,

也即变量在线程间隔离而在方法或类间共享的场景。

下图可以增强理解:

三、与Synchronized的区别

ThreadLocal其实就是与线程绑定的一个变量。

ThreadLocal和Synchonized都用于解决多线程并发访问。

但是ThreadLocal与synchronized有本质的区别:

  1. Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离。
  2. Synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每

一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离

了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得

数据共享。

一句话理解ThreadLocal,threadlocl是作为当前线程中属性ThreadLocalMap集合中的某一个Entry

的key值Entry(threadlocl,value),虽然不同的线程之间threadlocal这个key值是一样,但是不同

的线程所拥有的ThreadLocalMap是独一无二的,也就是不同的线程间同一个ThreadLocal(key)

对应存储的值(value)不一样,从而到达了线程间变量隔离的目的,但是在同一个线程中这个 value

变量地址是一样的。

四、基本使用

直接上代码:

/**
 * @projectName: 02JUC
 * @ClassName ThreadLocaDemo01
 * @description:
 * @author: CodingW
 * @create: 2025.01.17.15:14
 * @Version 1.0
 **/
public class ThreadLocaDemo01 {

    private static ThreadLocal<String> localVar = new ThreadLocal<String>();

  
package com.example.kucun2.entity.data; import android.os.Handler; import android.os.Looper; import android.util.Log; import com.example.kucun2.entity.Information; import com.example.kucun2.entity.RefTo; import com.example.kucun2.entity.RefType; import com.example.kucun2.function.MyAppFunction; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; /** * 可同步实体基类 * 实现实体状态管理、属性变更监听、服务端同步等功能 */ public abstract class SynchronizableEntity implements EntityClassGrassrootsid { // 实体同步状态枚举 private static boolean syncEnabled = true; // 全局同步开关 // 属性变更支持 private transient PropertyChangeSupport changeSupport = new PropertyChangeSupport(this); // 同步锁和回调队列 private final Object syncLock = new Object(); private final List<SyncCallback> pendingCallbacks = new ArrayList<>(); //================ 基础方法 ================// /** 判断是否为预保存对象 */ public boolean isPreservedObject() { return this.getId() != null && this.getId() == -1; } /** 设置全局同步开关 */ public static void setSyncEnabled(boolean enabled) { syncEnabled = enabled; } /** 获取/设置实体状态 */ public SyncState getState() { return this.state; } public void setState(SyncState state) { this.state = state; } //================ 属性变更监听 ================// /** 添加属性变更监听器 */ public void addPropertyChangeListener(PropertyChangeListener listener) { if (changeSupport == null) changeSupport = new PropertyChangeSupport(this); changeSupport.addPropertyChangeListener(listener); } /** 移除属性变更监听器 */ public void removePropertyChangeListener(PropertyChangeListener listener) { if (changeSupport != null) changeSupport.removePropertyChangeListener(listener); } //================ 端点URL生成 ================// /** 获取操作端点URL */ public String getEndpoint(String type) { String key = "url_" + type + "_" + this.getClass().getSimpleName().toLowerCase(); return MyAppFunction.getStringResource("string", key); } //================ 核心同步方法 ================// /** 执行同步操作 */ public void sync(SyncCallback callback) { if (!syncEnabled) return; // 检查全局开关 try { switch (this.state) { case NEW: createToServer(callback); break; case MODIFIED: updateToServer(callback); break; case DELETED: deleteFromServer(callback); break; } } catch (Exception e) { Log.e("SyncError", "Sync failed for " + getClass().getSimpleName(), e); } } //================ 服务端操作 ================// /** 更新实体到服务端 */ private void updateToServer(SyncCallback callback) { String endpoint = MyAppFunction.getStringResource("string", "url") + getEndpoint("update") + "/" + getId(); // 实现与createToServer类似... } /** 从服务端删除实体 */ private void deleteFromServer(SyncCallback callback) { String endpoint = MyAppFunction.getStringResource("string", "url") + getEndpoint("delete") + "/" + getId(); // 实现与createToServer类似... } //================ 依赖管理 ================// /** 添加需要同步的依赖实体 */ private void addDependencyIfRequired(SynchronizableEntity entity, List<SynchronizableEntity> dependencies) { if (!entity.isPreservedObject() && entity.requiresSync()) { dependencies.add(entity); } } //================ 回调接口 ================// @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; return Objects.equals(getId(), ((SynchronizableEntity) o).getId()); } // 同步状态枚举 public enum SyncState { NEW, MODIFIED, DELETED, SYNCING, SYNCED, PRESERVED } private SyncState state = SyncState.NEW; private static final int MAX_RETRY = 3; private int retryCount = 0; private static final Map<String, Boolean> syncLocks = new ConcurrentHashMap<>(); private static final ThreadLocal<Set<String>> syncStack = ThreadLocal.withInitial(HashSet::new); // 触发属性变更时自动同步 protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { if (changeSupport != null && changeSupport.hasListeners(propertyName)) { propertyCache/*报红未定义*/.put(propertyName, newValue); changeSupport.firePropertyChange(propertyName, oldValue, newValue); } // 状态为SYNCED时标记为需要同步 if (state == SyncState.SYNCED) { state = SyncState.MODIFIED; } // 启动同步(非新建实体) if (state != SyncState.NEW && state != SyncState.SYNCING) { scheduleSync(); } } // 安排同步任务(防止频繁同步) private void scheduleSync() { String lockKey = this.getClass().getName() + getId(); synchronized (syncLocks) { if (syncLocks.containsKey(lockKey)) return; syncLocks.put(lockKey, true); } new Handler(Looper.getMainLooper()).postDelayed(() -> { syncWithDependencies(null); synchronized (syncLocks) { syncLocks.remove(lockKey); } }, 1000); // 1秒延迟 } /** * 带依赖关系的同步方法 * * 根据 @RefTo 注解的依赖关系,确保: * 1. 双向关联的反向字段会同步更新 * 2. 列表关联的所有元素会按顺序同步 * 3. 单引用实体优先同步 * * @param callback 同步完成回调 */ public void syncWithDependencies(SyncCallback callback) { // 检测循环依赖 String entityKey = this.getClass().getName() + getId(); Set<String> currentStack = syncStack.get(); if (currentStack.contains(entityKey)) { Log.w("Sync", "检测到循环依赖: " + entityKey); if (callback != null) callback.onSyncFailure("循环依赖"); return; } currentStack.add(entityKey); state = SyncState.SYNCING; try { // 获取所有依赖实体 List<Dependency> dependencies = getDependencies(); if (dependencies.isEmpty()) { syncInternal(callback); return; } // 同步所有依赖实体 AtomicInteger counter = new AtomicInteger(dependencies.size()); for (Dependency dep : dependencies) { dep.entity.syncWithDependencies(new SyncCallback() { @Override public void onSyncSuccess(SynchronizableEntity entity) { // 处理双向关联的反向字段 if (dep.isBidirectional) { updateReverseField(dep, entity); } if (counter.decrementAndGet() == 0) { syncInternal(callback); } } @Override public void onSyncFailure(String error) { if (callback != null) { callback.onSyncFailure(error); } state = SyncState.MODIFIED; // 重置状态 } }); } } finally { currentStack.remove(entityKey); } } // 更新双向关联的反向字段 private void updateReverseField(Dependency dep, SynchronizableEntity updatedEntity) { try { Field reverseField = dep.targetType.getDeclaredField(dep.reverseFieldName); reverseField.setAccessible(true); if (dep.refType == RefType.SINGLE) { // 单引用反向设置 reverseField.set(updatedEntity, this); } else if (dep.refType == RefType.LIST) { // 列表引用反向添加 @SuppressWarnings("unchecked") List<SynchronizableEntity> list = (List<SynchronizableEntity>) reverseField.get(updatedEntity); if (list == null) { list = new ArrayList<>(); reverseField.set(updatedEntity, list); } if (!list.contains(this)) { list.add(this); } } } catch (Exception e) { Log.e("Sync", "更新反向字段失败", e); } } // 实际同步逻辑 private void syncInternal(SyncCallback callback) { switch (state) { case NEW: createToServer(callback); break; case MODIFIED: updateToServer(callback); break; case DELETED: deleteFromServer(callback); break; default: if (callback != null) callback.onSyncSuccess(this); } } // 依赖关系描述类 private static class Dependency { SynchronizableEntity entity; Class<?> targetType; RefType refType; boolean isBidirectional; String reverseFieldName; Dependency(SynchronizableEntity entity, Class<?> targetType, RefType refType, boolean isBidirectional, String reverseFieldName) { this.entity = entity; this.targetType = targetType; this.refType = refType; this.isBidirectional = isBidirectional; this.reverseFieldName = reverseFieldName; } } /** * 获取所有依赖实体 * * 根据 @RefTo 注解解析: * - target: 目标实体类型 * - type: 引用类型(SINGLE/LIST) * - bidirectional: 是否双向关联 * - reverseField: 反向字段名 */ private List<Dependency> getDependencies() { List<Dependency> dependencies = new ArrayList<>(); for (Field field : this.getClass().getDeclaredFields()) { try { field.setAccessible(true); RefTo refAnnotation = field.getAnnotation(RefTo.class); if (refAnnotation == null) continue; Object value = field.get(this); Class<?> targetType = refAnnotation.target(); RefType refType = refAnnotation.type(); boolean bidirectional = refAnnotation.bidirectional(); String reverseField = refAnnotation.reverseField(); if (refType == RefType.SINGLE && value instanceof SynchronizableEntity) { SynchronizableEntity entity = (SynchronizableEntity) value; if (entity.requiresSync()) { dependencies.add(new Dependency(entity, targetType, refType, bidirectional, reverseField)); } } else if (refType == RefType.LIST && value instanceof List) { for (Object item : (List<?>) value) { if (item instanceof SynchronizableEntity) { SynchronizableEntity entity = (SynchronizableEntity) item; if (entity.requiresSync()) { dependencies.add(new Dependency(entity, targetType, refType, bidirectional, reverseField)); } } } } } catch (Exception e) { Log.e("Sync", "获取依赖失败", e); } } // 确保单引用实体优先同步 dependencies.sort((d1, d2) -> { if (d1.refType == RefType.SINGLE && d2.refType != RefType.SINGLE) return -1; if (d1.refType != RefType.SINGLE && d2.refType == RefType.SINGLE) return 1; return 0; }); return dependencies; } // 创建到服务器 private void createToServer(SyncCallback callback) { String endpoint = getEndpoint("add"); Information<SynchronizableEntity> request = new Information<>(200, "Create", this); ApiClient.post(endpoint, request, new ApiClient.ApiCallback<SynchronizableEntity>() { @Override public void onSuccess(Information<SynchronizableEntity> response) { if (response.getData() != null) { setId(response.getData().getId()); // 设置服务器ID } state = SyncState.SYNCED; if (callback != null) callback.onSyncSuccess(SynchronizableEntity.this); } @Override public void onError(int statusCode, String error) { handleSyncError(error, callback); } }); } // 错误处理(带重试机制) private void handleSyncError(String error, SyncCallback callback) { if (retryCount < MAX_RETRY) { retryCount++; new Handler(Looper.getMainLooper()).postDelayed(() -> syncWithDependencies(callback), 3000); } else { state = SyncState.MODIFIED; retryCount = 0; if (callback != null) callback.onSyncFailure(error); } } // 检查是否需要同步 boolean requiresSync() { return state == SyncState.NEW || state == SyncState.MODIFIED || state == SyncState.DELETED; } // 同步回调接口 public interface SyncCallback { void onSyncSuccess(SynchronizableEntity entity); void onSyncFailure(String error); } }
06-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodingW丨编程之路

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值