2

エラーは次のようになります

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;
    }

古いエントリを自動的に削除するマップを作成したかったので、このスニペットを使用しました

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 です。しかし、内部でクラッシュするのはなぜですか? 関数全体に try/catch を配置するだけに頼らずに、これを修正しようとしていgetLastFinishedCommandsます。

古いジャンクから自動的に消去されますが、少なくとも 5000 個のキー/値エントリを保持するマップが必要です。

4

2 に答える 2

5

スタックトレースに基づいて、コードは、別のスレッドによって項目が既に削除されているインデックスから値を削除しようとしていると想定しています。これによりNPE、参照のプロパティにアクセスしているときにスローされnullます。おそらく、コレクションを同期してみてください

のドキュメントからLinkedHashMap

この実装は同期されていないことに注意してください。複数のスレッドがリンクされたハッシュ マップに同時にアクセスし、少なくとも 1 つのスレッドがマップを構造的に変更する場合は、外部で同期する必要があります。これは通常、マップを自然にカプセル化するオブジェクトを同期することによって実現されます。そのようなオブジェクトが存在しない場合は、Collections.synchronizedMap メソッドを使用してマップを「ラップ」する必要があります。これは、マップへの偶発的な非同期アクセスを防ぐために、作成時に行うのが最適です。

   Map m = Collections.synchronizedMap(new LinkedHashMap(...));
于 2014-04-01T07:16:00.057 に答える