为了账号安全,请及时绑定邮箱和手机立即绑定

并发哈希图删除复杂值

并发哈希图删除复杂值

拉风的咖菲猫 2023-12-13 14:31:31
我有哈希映射:private final ConcurrentHashMap<String, List<Client>> clients;和班级:public static class Client {    private String name; // it is also the key of the map    private String url;}我从多个线程中调用线程安全方法“ removeElement ”,该方法必须从列表中删除一个值。@Overridepublic CompletableFuture<Void> removeClient(Client client) {    return CompletableFuture.runAsync(() ->            clients.entrySet().removeIf(v ->                    v.getValue().removeIf(                            it -> client.url.equals(it.url))            )    );}但当然,这是行不通的。当我得到 Method throws 'java.lang.UnsupportedOperationException' 异常时,我解决了这样的问题:@Overridepublic CompletableFuture<Void> removeClient(Client client) {    return CompletableFuture.runAsync(() -> {                List<Client> currentClients = new ArrayList<>(clients.get(client.getName()));                currentClients.remove(client);                if (currentClients.isEmpty()) {                    clients.remove(client.getName());                } else {                    clients.put(client.getName(), currentClients);                }            }    );}但它不是线程安全的。我怎样才能在这里实现它?也许有更优雅的方法来解决它?
查看完整描述

1 回答

?
Cats萌萌

TA贡献1805条经验 获得超9个赞

我认为您可以ConcurrentHashMap::computeIfPresent在这种情况下使用假设相同的List实例没有放置相同的键:

CompletableFuture.runAsync(() -> {

    clients.computeIfPresent(client.getName(), (name, clients1) -> {

        List<Client> currentClients = new ArrayList<>(clients1);

        currentClients.remove(client);

        return currentClients.isEmpty() ? null : currentClients;

    });

});

由于computeIfPresent是原子执行的,并且我们在 remappingFunction 中使用列表的副本 - 它应该可以工作。


正如我们在文档中可以读到的:


如果指定键的值存在,则尝试计算给定键及其当前映射值的新映射。整个方法调用都是原子执行的。当计算正在进行时,其他线程对此映射的某些尝试更新操作可能会被阻止,因此计算应该简短且简单,并且不得尝试更新此映射的任何其他映射。


查看完整回答
反对 回复 2023-12-13
  • 1 回答
  • 0 关注
  • 101 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信