1

我有一个类来管理多个功能的锁定对象。我发现 WeakHashMap 应该符合我的要求。这是我的代码:

public static class FeatureLockManager {
        private final Map<Object, WeakKeyLockPair> locks;
        private String domain;

        public FeatureLockManager(String domain) {
            this.domain = domain;
            locks = new WeakHashMap<Object, WeakKeyLockPair>();
        }

        public Lock getLock(Object feature) {
            if (locks.get(feature) == null) {
                synchronized (locks) {
                    locks.computeIfAbsent(feature, l -> new WeakKeyLockPair(feature, new ReentrantLock()));
                }
            }
            return locks.get(feature);
        }

        private static class WeakKeyLockPair implements Lock {
            private final Reference<Object> feature;
            private final Lock lock;

            private WeakKeyLockPair(Object feature, Lock lock) {
                this.feature = new WeakReference<Object>(feature);
                this.lock = lock;
            }
...      }
       }

但是,做了一个简单的测试后,我意识到锁对象在GC之后不会被删除。

public static void main(String[] args) throws InterruptedException {
        FeatureLockManager test = new FeatureLockManager("test");
        Lock lock = test.getLock("add user");
        System.out.println(lock.hashCode());
        // do thing
        System.gc();
        Thread.sleep(1000);
        Lock lock1 = test.getLock("add user");
        System.out.println(lock1.hashCode());
        System.out.println(lock1 == lock);
    }

你能告诉我我的实施有什么问题吗?先感谢您!

4

2 回答 2

2

根据 WeakHashMap 的 java 文档

WeakHashMap 中的每个键对象都间接存储为弱引用的所指对象。因此,只有在映射内部和外部的弱引用已被垃圾收集器清除后,才会自动删除键。

您的 FeatureLockManager 类仍然具有对 WeakHashMap 的关键元素(“添加用户”)的强引用。

有关更多详细信息,请查看文档

于 2019-12-12T11:18:16.923 回答
2

我认为这是因为您在映射中使用字符串作为键,字符串存储在通用字符串池内存中,并且程序的不同部分将使用相同的文字值,因此它不会有资格进行 GC,我建议使用不同的对象类型或原始包装类型(例如尝试整数表示)或字符串以外的任何其他对象

于 2019-12-12T11:25:06.093 回答