Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 并发哈希映射删除复杂值_Java_Multithreading_Dictionary_Thread Safety - Fatal编程技术网

Java 并发哈希映射删除复杂值

Java 并发哈希映射删除复杂值,java,multithreading,dictionary,thread-safety,Java,Multithreading,Dictionary,Thread Safety,我有HashMap: private final ConcurrentHashMap<String, List<Client>> clients; 从多个线程中,我调用线程安全方法“removeElement”,该方法必须从列表中删除一个值 @Override public CompletableFuture<Void> removeClient(Client client) { return CompletableFuture.runAsync((

我有HashMap:

private final ConcurrentHashMap<String, List<Client>> clients;
从多个线程中,我调用线程安全方法“removeElement”,该方法必须从列表中删除一个值

@Override
public CompletableFuture<Void> removeClient(Client client) {
    return CompletableFuture.runAsync(() ->
            clients.entrySet().removeIf(v ->
                    v.getValue().removeIf(
                            it -> client.url.equals(it.url))
            )
    );
}
@覆盖
公共CompletableFuture removeClient(客户端){
返回CompletableFuture.runAsync(()->
clients.entrySet().removeIf(v->
v、 getValue().removeIf(
it->client.url.equals(it.url))
)
);
}
但当然,这是行不通的。当我得到抛出“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);
                }
            }
    );
}
@覆盖
公共CompletableFuture removeClient(客户端){
返回CompletableFuture.runAsync(()->{
List currentClients=newarraylist(clients.get(client.getName());
currentClients.remove(客户端);
if(currentClients.isEmpty()){
clients.remove(client.getName());
}否则{
clients.put(client.getName(),currentClients);
}
}
);
}
但它不是线程安全的。我如何在这里实现它?也许有更优雅的方法来解决这个问题?

我认为您可以在这种情况下使用,假设相同的
列表
实例不适用于相同的键:

CompletableFuture.runAsync(() -> {
    clients.computeIfPresent(client.getName(), (name, clients1) -> {
        List<Client> currentClients = new ArrayList<>(clients1);
        currentClients.remove(client);
        return currentClients.isEmpty() ? null : currentClients;
    });
});
CompletableFuture.runAsync(()->{
clients.computefpresent(client.getName(),(name,clients1)->{
List CurrentClient=new ArrayList(客户端1);
currentClients.remove(客户端);
返回currentClients.isEmpty()?null:currentClients;
});
});
由于
computeIfPresent
是以原子方式执行的,并且我们在remappingFunction中使用了列表的副本,所以它应该可以工作

正如我们在文件中看到的:

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

CompletableFuture.runAsync(() -> {
    clients.computeIfPresent(client.getName(), (name, clients1) -> {
        List<Client> currentClients = new ArrayList<>(clients1);
        currentClients.remove(client);
        return currentClients.isEmpty() ? null : currentClients;
    });
});