带有removeEldestEntry的Java LinkedHashMap导致java.lang.NullPointerException [英] Java LinkedHashMap with removeEldestEntry causes java.lang.NullPointerException

查看:297
本文介绍了带有removeEldestEntry的Java LinkedHashMap导致java.lang.NullPointerException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

错误看起来像这样

Exception in thread "Thread-1" java.lang.NullPointerException
    at java.util.LinkedHashMap$Entry.remove(LinkedHashMap.java:332)
    at java.util.LinkedHashMap$Entry.recordAccess(LinkedHashMap.java:356)
    at java.util.LinkedHashMap.get(LinkedHashMap.java:304)
    at Server.getLastFinishedCommands(Server.java:9086)
    at Server.processPacket(Server.java:484)
    at PacketWorker.run(PacketWorker.java:34)
    at java.lang.Thread.run(Thread.java:744)

里面 getLastFinishedCommands 我使用

   public List<CCommand> getLastFinishedCommands(UserProfile player) {
        List<CCommand> returnList = new ArrayList<CCommand>();

        if(!finishedCommands.containsKey(player.myWebsitecmd-1)) {
            getSavedState(player);
            return null;
        }

        try { //<-- added this try/catch so it doesn't happen again.
            //Get commands.
            CCommand cmd;
            long i;
            long startIndex = player.myWebsitecmd;
            long endIndex = startIndex+LIMIT_COMMANDS;

            for(i = startIndex; i <= endIndex; i++) {
                cmd = finishedCommands.get(i);   //<-- this is line 9086
                if(cmd == null) {
                    return returnList;
                }
                returnList.add(cmd);
            }
        } catch(Exception e) {} //<-- added this try/catch so it doesn't happen again.
        return returnList;
    }

我想制作一个自动删除旧条目的地图,所以我使用这个代码段

I wanted to make a Map that auto removes old entries so I used this snippet

public static <K, V> Map<K, V> createLRUMap(final int maxEntries) {
    return new LinkedHashMap<K, V>(maxEntries*3/2, 0.7f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            return size() > maxEntries;
        }
    };
}

使用它像这样

public static int final MAX_COMMANDS_QUEUE = 5000;
public Map<Long, CCommand> finishedCommands = createLRUMap(MAX_COMMANDS_QUEUE);

显然,它是某种CocurrentModifcationException,当使用多个线程时会发生,但为什么它会在内部崩溃任何人都知道我可以像CocurrentHashMap一样使用它吗?我正在尝试解决这个问题,而不用仅仅在整个 getLastFinishedCommands 函数中放置一个try / catch。

Obviously it's some kind of CocurrentModifcationException which happens when using with multiple threads.. but why does it crash internally, anyone know how I can use this with like a CocurrentHashMap? I'm trying to fix this without resorting to just putting a try/catch around the whole getLastFinishedCommands function.

我想要一个从旧垃圾中清除的地图,但仍保留至少5000个键/值条目。

I want a Map that clears itself from old junk but still holds atleast 5000 key/value entries.

推荐答案

你说多个线程正在访问此地图。这实际上可以导致删除 c $ c> LinkedHashMap.Entry 实例中的NPE。这是这种方法的实现:

You said that multiple threads are accessing this map. This could indeed cause the NPE in the remove operation of a LinkedHashMap.Entry instance. This is the implementation of this method:

private void remove() {
    before.after = after;
    after.before = before;
}

这里之前和之后引用到当前条目的链接前代和后继。如果另一个线程已经更改了条目之间的链接,这当然可能会导致意外的行为,例如NPE。

Here before and after refer to the linked predecessor and successor of the current entry. If another thread already changed the linking between the entries, this could of course result in an unexpected behavior, such as the NPE.

解决方案是 - 你猜对了 - 将生成的地图包装在同步的地图中。例如:

The solution is - you guessed correctly - to wrap your produced map in a synchronized map. Such as:

public static <K, V> Map<K, V> createLRUMap(final int maxEntries) {
    Map<K,V> result = new LinkedHashMap<K, V>(maxEntries*3/2, 0.7f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            return size() > maxEntries;
        }
    };
    return Collections.synchronizedMap(result);
}

这个同步包装器确实将所有调用同步到底层地图,所以只有一个单线程允许通过每种方法(如get,put,contains,size等)。

This synchronized wrapper will indeed synchronize all calls to the underlying map, so only one single thread is allowed to go through each method (such as get, put, contains, size, and so on).

这篇关于带有removeEldestEntry的Java LinkedHashMap导致java.lang.NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆