在 Java 多线程编程里,合理运用全局变量缓存数据,能有效优化性能、提升效率。本文将为你详细介绍三种常见的实现方式,帮你应对不同场景下的缓存需求。
一、基础实现:HashMap + 手动锁
(一)场景需求
当需要简单的缓存结构,且需自主控制线程安全时,可采用 HashMap 配合手动加锁的方式。适用于对缓存逻辑有定制化需求,或需深入理解线程安全控制的场景。
(二)代码示例
            
            
              java
              
              
            
          
          import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
public class GlobalVariableCacheExample1 {
    // 定义全局缓存,用 HashMap 存储数据
    private static Map<String, Object> cache = new HashMap<>();
    // 可重入锁,保障多线程下读写安全
    private static final ReentrantLock lock = new ReentrantLock();
    // 从缓存获取数据
    public static Object getFromCache(String key) {
        lock.lock();
        try {
            return cache.get(key);
        } finally {
            lock.unlock();
        }
    }
    // 向缓存存入数据
    public static void putIntoCache(String key, Object value) {
        lock.lock();
        try {
            cache.put(key, value);
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        // 模拟多线程操作缓存
        Thread thread1 = new Thread(() -> {
            putIntoCache("key1", "value1");
            System.out.println("Thread1: " + getFromCache("key1"));
        });
        Thread thread2 = new Thread(() -> {
            putIntoCache("key2", "value2");
            System.out.println("Thread2: " + getFromCache("key2"));
        });
        thread1.start();
        thread2.start();
    }
}
        (三)实现原理与要点
- 线程安全保障 :借助 
ReentrantLock,在读写缓存的关键代码段加锁、解锁,确保同一时刻只有一个线程能操作缓存,避免多线程并发冲突。 - 使用注意 :加锁、解锁需在 
try-finally块中,保证锁能释放,防止死锁。不过,手动加锁会一定程度增加代码复杂度与执行开销。 
二、高效并发:ConcurrentHashMap
(一)场景需求
若追求简洁且高效的线程安全缓存,ConcurrentHashMap 是首选。它内部通过分段锁机制,在多线程高并发场景下,能有效提升读写效率,减少线程阻塞。适用于对性能要求较高的缓存场景。
(二)代码示例
            
            
              java
              
              
            
          
          import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class GlobalVariableCacheExample2 {
    // 线程安全的 ConcurrentHashMap 作为缓存
    private static Map<String, Object> cache = new ConcurrentHashMap<>();
    // 获取缓存数据,直接调用内置方法
    public static Object getFromCache(String key) {
        return cache.get(key);
    }
    // 存入缓存数据,调用内置方法
    public static void putIntoCache(String key, Object value) {
        cache.put(key, value);
    }
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            putIntoCache("key1", "value1");
            System.out.println("Thread1: " + getFromCache("key1"));
        });
        Thread thread2 = new Thread(() -> {
            putIntoCache("key2", "value2");
            System.out.println("Thread2: " + getFromCache("key2"));
        });
        thread1.start();
        thread2.start();
    }
}
        (三)实现原理与要点
- 线程安全机制 :
ConcurrentHashMap内部采用分段锁,把数据分成多个段,线程操作不同段时互不干扰,大幅提升并发性能。 - 优势 :无需手动加锁,代码简洁;并发场景下,比 
HashMap + 锁效率更高,减少线程等待时间。 
三、功能增强:Guava Cache
(一)场景需求
当缓存需更丰富的功能,如设置缓存容量上限、过期时间、自动加载数据等,Guava Cache 能满足需求。适用于对缓存管理有精细化要求的业务场景。
(二)依赖配置(Maven)
在项目 pom.xml 中添加 Guava 依赖:
            
            
              XML
              
              
            
          
          <dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
</dependency>
        (三)代码示例
            
            
              java
              
              
            
          
          import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class GlobalVariableCacheExample3 {
    // 构建 Guava Cache,配置容量、过期时间等
    private static LoadingCache<String, Object> cache = CacheBuilder.newBuilder()
           .maximumSize(100) // 缓存最大容量
           .expireAfterWrite(10, TimeUnit.MINUTES) // 写入后 10 分钟过期
           .build(new CacheLoader<String, Object>() {
                @Override
                public Object load(String key) throws Exception {
                    // 缓存未命中时,加载数据的逻辑,这里简单返回 null
                    return null;
                }
            });
    // 获取缓存数据,处理可能的异常
    public static Object getFromCache(String key) {
        try {
            return cache.get(key);
        } catch (ExecutionException e) {
            e.printStackTrace();
            return null;
        }
    }
    // 存入缓存数据
    public static void putIntoCache(String key, Object value) {
        cache.put(key, value);
    }
    public static void main(String[] args) {
        Thread thread1 = new Thread(() -> {
            putIntoCache("key1", "value1");
            System.out.println("Thread1: " + getFromCache("key1"));
        });
        Thread thread2 = new Thread(() -> {
            putIntoCache("key2", "value2");
            System.out.println("Thread2: " + getFromCache("key2"));
        });
        thread1.start();
        thread2.start();
    }
}
        (四)实现原理与要点
- 缓存配置 :通过 
CacheBuilder配置缓存参数,如最大容量、过期策略,灵活管控缓存资源。 - 自动加载 :
CacheLoader实现缓存未命中时的数据加载逻辑,让缓存使用更智能。 - 异常处理 :
get方法可能抛出ExecutionException,需捕获并处理,保障程序健壮性。 
四、三种方式对比与选型建议
| 实现方式 | 线程安全保障 | 功能丰富度 | 代码复杂度 | 适用场景 | 
|---|---|---|---|---|
| HashMap + 手动锁 | 手动加锁控制 | 基础 | 较高 | 需深度定制锁逻辑的场景 | 
| ConcurrentHashMap | 内部分段锁 | 基础 | 低 | 高并发、追求简洁高效的场景 | 
| Guava Cache | 内部机制保障 | 丰富 | 中等 | 需精细化缓存管理的场景 | 
根据项目实际需求,若追求简单高效,选 ConcurrentHashMap;需定制锁逻辑,用 HashMap + 手动锁;要复杂缓存策略,就选 Guava Cache 。合理运用这些方式,让多线程缓存助力程序性能提升!