通过并发删除维护名称的唯一对象

2023-12-21

我正在使用以下编程习惯。我保持同步 HashMap 具有名称与对象的关联。要查找 对象的名称我使用以下代码:

MyObject getObject(String name) {
   synchronized(map) {
      MyObject obj = map.get(name);
      if (obj == null) {
         obj = new MyObjec();
         map.put(name, obj);
      }
   }
}

当我想专门研究这样一个物体时,我 将在这样的对象上使用同步:

synchronized(obj) {
    /* do something exclusively on obj (work type I) */
}

到目前为止,这一直运行良好,直到最近。新的 要求是有I型和II型除外 作品。 I 类将保留该对象,而 II 类应删除 完成工作后的对象。如果我做某事 沿着以下:

synchronized(obj) {
    /* do something exclusively on obj (work type II) */
}
synchronized(map) { /* not good! */
   map.remove(obj);
}

我可能会授予某些对象某种我工作的类型,尽管 对象已从地图中删除。所以基本上 类型 I 工作的同步(obj)应该被替换 通过一些新的信号量将对象重新连接到地图 如果之前已授予 II 类作品。分别 该对象仅应在未同步时离开地图 正在等待它。

最好是看不到这些物体。我会去 使用仅包含名称的 API。对象只是 用于维护名称的某种状态。但是HashMap 第二类作品完成后应从名称中删除 完全的。但是在类型 I 或类型 II 工作期间,HashMap 不应被锁定。

有什么想法如何做到这一点吗?这是已知的模式吗?

Bye


要求似乎是这样的:

  • 有一个Map<String, Object>那是一个缓存。
  • 池中有许多工作线程访问缓存
  • 某些类型的工作需要在完成后使缓存中的对象失效

首先你需要一个ConcurrentHashMap<String, Lock> keys. This Map将存储之间的关系String键和和Lock我们将使用锁钥匙的对象。这使我们能够替换key -> value无需锁定整个数据的映射Map.

接下来你将需要一个ConcurrentHashMap<String, Object> data. This Map将存储实际的映射。

使用的原因ConcurrentHashMap而不是普通的一个是它是线程安全的。这意味着不需要手动同步。该实现实际上划分了Map分成扇区并仅锁定所需的扇区来执行操作 - 这使其更加高效。

现在,逻辑将是

  1. putIfAbsent a new ReentrantLock into keys。这将以线程安全的方式检查是否已经存在锁key。如果没有,则添加新的,否则检索现有的。这意味着一把钥匙只能有一把锁
  2. 获得一把锁。这意味着您获得了对映射的独占访问权限。
  3. 做工作。如果是TypeII从中删除映射data完成后。
  4. 解锁。

代码看起来像这样:

private final ConcurrentHashMap<String, Object> data = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Lock> keys = new ConcurrentHashMap<>();
private final ExecutorService executorService = null; //obviously make one of these

@RequiredArgsConstructor
private class TypeI implements Runnable {

    private final String key;
    private final Work work;

    @Override
    public void run() {
        final Lock lock = keys.putIfAbsent(key, new ReentrantLock());
        lock.lock();
        try {
            final Object value = data.get(key);
            work.doWork(value);
        } finally {
            lock.unlock();
        }
    }
}

@RequiredArgsConstructor
private class TypeII implements Runnable {

    private final String key;
    private final Work work;

    @Override
    public void run() {
        final Lock lock = keys.putIfAbsent(key, new ReentrantLock());
        lock.lock();
        try {
            final Object value = data.get(key);
            work.doWork(value);
            data.remove(key);
        } finally {
            lock.unlock();
        }
    }
}

public static interface Work {

    void doWork(Object value);
}

public void doTypeIWork(final String key, final Work work) {
    executorService.submit(new TypeI(key, work));
}

public void doTypeIIWork(final String key, final Work work) {
    executorService.submit(new TypeII(key, work));
}

我用过Lombok注释以减少混乱。

这个想法是最小化或几乎消除公共资源锁定的数量,同时仍然允许Thread如果需要,获得对特定映射的独占访问权。

清洁按键Map您需要保证当前没有任何工作正在进行,并且没有Thread在清理期间,s 会尝试获取任何锁。您可以通过尝试获取相关锁,然后从键映射中删除映射来完成此操作 - 这将确保当时没有其他线程正在使用该锁。

您可以运行一个计划任务,例如每 X 分钟从地图中清除 20 个键。如果您将其实现为 LRU 缓存,那么它应该相当干净。谷歌番石榴提供一个实现 http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/cache/Cache.html你可以使用的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

通过并发删除维护名称的唯一对象 的相关文章

随机推荐

  • objectid 的 mongodb 部分最有可能是唯一的

    在我的应用程序中 我让 mongo 通过其 ObjectId 方法生成订单 id 但在用户测试中 我们担心订单 ID 会让人感到 恐吓 即如果您需要通过电话与某人讨论您的订单 那么读出 24 个字母数字字符有点乏味 同时 我真的不想存储两个
  • 简单的PHP模板解析

    我想创建一个简单的 PHP 类 用于在 PHP 中解析基本的 HTML 电子邮件模板 非常基本 将 PHP 数组传递到一个函数中 该函数有一个包含带有占位符的电子邮件模板 HTML 的变量 var name PHP 数组的键将是模板中的变量
  • java.lang.NoClassDefFoundError: org/hibernate/cfg/Configuration

    我正在尝试在 Eclipse 中使用 Hibernate 进行初始设置 同时使用 Tomcat 进行部署 我遇到了以下问题 java lang ClassNotFoundException org hibernate cfg Configu
  • Android:AlarmManager 在过去的时间触发

    这是我的警报管理器代码 Intent intent new Intent getBaseContext AlarmReciever class intent setAction com example projectx ACTION Pen
  • 从 System.Type 初始化通用对象

    我需要创建一个泛型类型 但我在编译时不知道该类型 我想这样做 Type t typeof whatever var list new List
  • python3.0上的安装工具

    我试图为 python3 0 安装 setuptool 包 但不幸的是 我尝试安装它说模块名称 dist 丢失 请帮我解决这个问题 截至 2013 年 3 月的编辑 请查看下面已接受的答案 以获取 LennartRegebro 的最新回复
  • 如何访问Django模板中的动态键? [复制]

    这个问题在这里已经有答案了 请看下面的代码 for row in df src iterrows tr td td tr
  • cURL 加载时间太长

    我使用 cURL 调用 PHP 中的 REST 端点来获取一些 JSON 数据
  • 如何使用 Xcode 调试 dylib?

    我有一个 arith 库的 Xcode 项目 我可以使用调试配置来构建它 并且我需要调试它 我怎样才能做到这一点 理想的方法是设置测试代码以在项目文件中构建执行 然后在 arith 库的源代码中设置断点 但是 Xcode arith 项目似
  • 使用 flink runner 在梁上进行 Tensorflow 变换

    这可能看起来很愚蠢 但这是我在这里发表的第一篇文章 抱歉做错了什么 我目前正在使用 python2 7 使用 TFX 0 11 即 tfdv tft tfserving 和tensorflow 1 11 构建一个简单的 ML 管道 我目前有
  • 捆绑安装时出现致命错误(安装 libv8 时)

    我在 Windows 7 32 位 上工作 在捆绑安装时出现错误 Installing libv8 3 3 10 4 with native extensions Unfortunately a fatal error has occurr
  • 如何在组件ContextMenu中的primeNG中使用属性appendTo?

    我正在尝试使用该属性appendTo在组件中上下文菜单 https www primefaces org primeng contextmenu 但我想将行为附加到一个元素 例如 div 在您想要附加的元素上添加主题标签 myHashTag
  • 查找沿轴不包括零的 numpy 数组的最小值/最大值

    有一种很好的方法可以找到数组中不包括零的非零最小值 最大值here https stackoverflow com questions 7164397 find the min max excluding zeros in a numpy
  • 将表单 POST 与查询字符串组合是否有效?

    例如 我知道在大多数 MVC 框架中 查询字符串参数和表单参数都可供处理代码使用 并且通常合并为一组参数 通常 POST 优先 但是 根据 HTTP 规范 这样做是否有效 假设您要发布到 http 1 2 3 4 MyApplication
  • Powershell:如何测试一行文本是否包含换行符或回车符?

    如何测试文本文件的第一行是否以 r 或 n 终止 我尝试了类似于以下的各种演绎 我不确定导入到 powershell 中的字符串 文件的第一行 是否包含不可见字符 我也尝试使用 StreamReader 方法读取该行 但无济于事 maste
  • 如何导出C#方法?

    我们如何导出 C 方法 我有一个 dll 我想通过 ctypes 模块在 Python 语言中使用它的方法 因为我需要使用 ctypes 模块 所以我需要导出 C 方法 以便它们在 Python 中可见 那么 如何导出 C 方法 就像在 C
  • 更改 gridview 以呈现 head 元素

    我看过一些其他关于如何实现此功能的帖子 但是 它们似乎都不关心您将 GridView 子类化为您自己的自定义服务器控件的情况 我试图设置这些属性以使 GridView 呈现 thead 元素 但我不断收到空引用异常 有接受者吗 这是 Dat
  • CoordinatorLayout 内的水平 RecyclerView

    我是 Android 开发新手 我正在 android lollipop 设备中使用 CoordinatorLayout 问题是 我有一个具有水平滚动的回收器视图 在滚动具有垂直滚动效果的回收器视图时会折叠 如果我不滚动水平回收器视图 如果
  • 最后一个窗口关闭时关闭 SwiftUI 应用程序[重复]

    这个问题在这里已经有答案了 当用户关闭最后一个窗口时 是否可以关闭 macOS SwiftUI 应用程序 类似于applicationShouldTerminateAfterLastWindowClosed应用程序委托函数 func app
  • 通过并发删除维护名称的唯一对象

    我正在使用以下编程习惯 我保持同步 HashMap 具有名称与对象的关联 要查找 对象的名称我使用以下代码 MyObject getObject String name synchronized map MyObject obj map g