java - 并发 HashMap 删除复杂值

标签 java multithreading dictionary thread-safety

我有 HashMap:

private final ConcurrentHashMap<String, List<Client>> clients;

和类(class):

public static class Client {
    private String name; // it is also the key of the map
    private String url;
}

我从多个线程中调用线程安全方法“removeElement”,该方法必须从列表中删除一个值。

@Override
public 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' 异常时,我解决了这样的问题:

@Override
public 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);
                }
            }
    );
}

但它不是线程安全的。我怎样才能在这里实现它?也许有更优雅的方法来解决它?

最佳答案

我认为你可以使用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 中使用列表的副本 - 它应该可以工作。

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

If the value for the specified key is present, attempts to compute a new mapping given the key and its current mapped value. The entire method invocation is performed atomically. Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map.

关于java - 并发 HashMap 删除复杂值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58533987/

相关文章:

java - Servlet 3.0 Spring Java 配置 JNDI

java - 线程操作和线程销毁的最佳实践?

java - 如何更新 map 中的 map ?

当它是一个数字时,Python 从字典中删除一个键

java - 在 Java 中使用 synchronized (Thread.currentThread()){...} 的目的是什么?

javascript - 在排序的 JavaScript 字典中查找前 3 个值条目?

java - puppetlabs-java Oracle 无法应用目录 : No title provided and :file is not a valid resource reference

java - XML 到哈希表

Java - 在这种情况下如何正确规避非法访问异常

python - 在 Python 2.7 中使用线程 smtpd 的 linux 和 os x 之间的奇怪行为差异