具有空键功能的线程安全映射

发布于 2024-11-02 04:11:10 字数 319 浏览 1 评论 0原文

我需要一个多线程 Map 对象在 Web 服务器的缓存中使用,并且需要有 null 键。

HashMap 允许我拥有 null 键,但 ConcurrentHashMap 不允许。我尝试使用 Collections.synchronizedMap(new HashMap()) 创建 HashMap 的同步版本,但它也不接受 null 键。

我可以使用任何替代方法,而不必实现某种方法来包装 null 键吗?

I need a multi-threaded Map object to use in my web server's caching, and I need to have null keys.

HashMap allows me to have null keys, but ConcurrentHashMap doesn't. I tried to create a synchronized version of HashMap using Collections.synchronizedMap(new HashMap()) but it doesn't accept null keys either.

Is there any alternative that I can use, without having to implement some way to wrap the null keys?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一腔孤↑勇 2024-11-09 04:11:10

Collections.synchronizedMap 支持您提供的 Map 的所有功能。如果你给它一个HashMap,它支持null键(还有null值,你说“......我需要具有“空”键值...“,可以以任何方式读取)。

这按预期工作,例如:

import java.util.*;

public class MapTest
{
    public static final void main(String[] args)
    {
        Map map;

        try
        {
            map = Collections.synchronizedMap(new HashMap());
            map.put("one", "a");
            System.out.println("Size = " + map.size());
            map.put(null, "b");
            System.out.println("Size = " + map.size());
            System.out.println("map.get(null) = " + map.get(null));
        }
        catch (Exception ex)
        {
            System.out.println("Exception: " + ex.getMessage());
            ex.printStackTrace(System.out);
        }
        System.exit(0);
    }
}

输出:

Size = 1
Size = 2
map.get(null) = b

同步映射存在同步问题。如果您可以解决对 null 键和值的需求,ConcurrentHashMap 可能是服务器缓存的更好选择。但它“...不允许 null 用作键或值。”


请注意,您需要从 synchronizedMap 手动同步地图。 code> 如果你想迭代。来自 JavaDoc

当用户通过 Iterator、Spliterator 或 Stream 遍历任何集合视图时,必须在返回的映射上手动同步:

...

不遵循此建议可能会导致不确定的行为。

地图会在 get 等方面为您处理它,但不会在迭代时处理。

The Map returned by Collections.synchronizedMap supports all of the features of the Map you give it. If you give it a HashMap, it supports the null key (and also null values, you said "...I need to have "null" key values..." which can be read either way).

This works as expected, for instance:

import java.util.*;

public class MapTest
{
    public static final void main(String[] args)
    {
        Map map;

        try
        {
            map = Collections.synchronizedMap(new HashMap());
            map.put("one", "a");
            System.out.println("Size = " + map.size());
            map.put(null, "b");
            System.out.println("Size = " + map.size());
            System.out.println("map.get(null) = " + map.get(null));
        }
        catch (Exception ex)
        {
            System.out.println("Exception: " + ex.getMessage());
            ex.printStackTrace(System.out);
        }
        System.exit(0);
    }
}

Output:

Size = 1
Size = 2
map.get(null) = b

A synchronized map has the issue that, well, it's synchronized. If you can work around the need for null keys and values, ConcurrentHashMap would probably be the better option for a server cache. But it "...does not allow null to be used as a key or value."


Note that you need to manually synchronize the map from synchronizedMap if you want to iterate. From the JavaDoc:

It is imperative that the user manually synchronize on the returned map when traversing any of its collection views via Iterator, Spliterator or Stream:

...

Failure to follow this advice may result in non-deterministic behavior.

The map handles it for you on get and such, but not iteration.

回忆躺在深渊里 2024-11-09 04:11:10

据我所知,既没有简单的方法来制作 ConcurrentHashMap ,也没有支持 null 键或值的等效类。

ConcurrentHashMapCollections.synchronizedMap(new HashMap()) 有很大不同。

首先,因为即使所有访问都是只读的,同步映射也会阻止任何并发访问同时发生。 ConcurrentHashMap 不会阻止并发读取访问,在某些情况下甚至可能接受并发写入。

但更重要的是,如果在使用迭代器时修改了底层映射,则同步映射返回的迭代器很容易抛出ConcurrentModificationException。另一方面,即使在使用迭代器时底层映射发生更改,ConcurrentHashMap 迭代器也保证永远不会抛出 ConcurrentModificationException

As far as I know there is neither a simple way to make ConcurrentHashMap nor an equivalent class supporting null keys or values.

ConcurrentHashMap is quite different from Collections.synchronizedMap(new HashMap()).

First of all because a synchronized map will prevent any concurrent accesses to happen simultaneously even if all accesses are read only. ConcurrentHashMap won't block concurrent read accesses and, in some cases, may even accept concurrent writes.

But the more important thing is that the Iterators returned by a synchronized map are prone to throw ConcurrentModificationException if the underlying map is modified while using the iterator. On the other hand, the ConcurrentHashMap iterators' are guaranteed to never throw ConcurrentModificationException even if the underlying map is changed while using the iterator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文