面试题答案
一键面试可能遇到的问题
- 数据一致性问题:多个线程同时对WeakHashMap进行读写操作时,可能导致数据不一致。例如,一个线程正在读取某个键值对,而另一个线程同时删除了该键值对,这可能使读取线程获取到无效数据。
- 并发修改异常:当多个线程同时修改WeakHashMap时,可能会抛出
ConcurrentModificationException
。这是因为WeakHashMap本身不是线程安全的,在迭代过程中如果结构发生改变(如添加或删除元素),就会触发该异常。 - 弱引用对象提前被回收:在多线程环境下,由于不同线程的执行顺序和时间不确定,可能导致弱引用对象在其他线程还在使用时就被垃圾回收机制提前回收,从而丢失数据。
解决方法
- 使用同步机制:
- 使用
synchronized
关键字:可以对WeakHashMap的关键操作(如put
、get
、remove
等)进行同步。示例代码如下:
- 使用
WeakHashMap<String, Object> weakHashMap = new WeakHashMap<>();
synchronized (weakHashMap) {
weakHashMap.put("key", "value");
Object value = weakHashMap.get("key");
weakHashMap.remove("key");
}
- **使用`Collections.synchronizedMap`**:可以将WeakHashMap包装成线程安全的Map。示例代码如下:
WeakHashMap<String, Object> weakHashMap = new WeakHashMap<>();
Map<String, Object> synchronizedWeakHashMap = Collections.synchronizedMap(weakHashMap);
synchronizedWeakHashMap.put("key", "value");
Object value = synchronizedWeakHashMap.get("key");
synchronizedWeakHashMap.remove("key");
- 使用并发包中的
ConcurrentHashMap
(类似替代方案):虽然ConcurrentHashMap
不是WeakHashMap的直接替代品,但在很多场景下,如果对弱引用特性需求不强烈,可以使用ConcurrentHashMap
来保证线程安全。它提供了高效的并发读写操作,并且不会抛出ConcurrentModificationException
。示例代码如下:
ConcurrentHashMap<String, Object> concurrentHashMap = new ConcurrentHashMap<>();
concurrentHashMap.put("key", "value");
Object value = concurrentHashMap.get("key");
concurrentHashMap.remove("key");
- 使用
WeakHashMap
结合ThreadLocal
:如果每个线程需要独立使用WeakHashMap,可以使用ThreadLocal
来为每个线程创建一个独立的WeakHashMap实例。示例代码如下:
ThreadLocal<WeakHashMap<String, Object>> threadLocalWeakHashMap = ThreadLocal.withInitial(WeakHashMap::new);
WeakHashMap<String, Object> threadSpecificWeakHashMap = threadLocalWeakHashMap.get();
threadSpecificWeakHashMap.put("key", "value");
Object value = threadSpecificWeakHashMap.get("key");
threadSpecificWeakHashMap.remove("key");
这样每个线程都有自己独立的WeakHashMap,避免了多线程竞争带来的问题。