3

XMLファイルを更新するスレッドim呼び出しがあります。

    public synchronized void updateVouchXML() {
        new Thread(new updateVouchXML((BotLinkedMap<String, IPlayer>)botList.getPlayerData().clone())).start();
    }

このスレッドのrunメソッドでは、マップのクローンを作成するときに同時変更エラーが発生します。私は以前に同時変更の問題に対処しましたが、通常の解決策は、繰り返し処理するオブジェクトを閉じることです。オブジェクトのクローンが例外を引き起こしたという問題は一度もありませんでした。何かアドバイス?

/**
*
* @author Mark
*/
public class updateVouchXML implements Runnable {

    BotLinkedMap<String, IPlayer> players;
    DocumentBuilderFactory dbf;
    DocumentBuilder db;
    Document doc;
    Element vdata;

    public updateVouchXML(BotLinkedMap<String, IPlayer> players) {

        this.players = players;
        dbf = DocumentBuilderFactory.newInstance();
        try {
            db = dbf.newDocumentBuilder();
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(updateVouchXML.class.getName()).log(Level.SEVERE, null, ex);
        }
        doc = db.newDocument();
    }

    @Override
    public void run() {
        try {


            vdata = doc.createElement("vouchdata");
            doc.appendChild(vdata);


            BotLinkedMap<String, IPlayer> clone = (BotLinkedMap<String, IPlayer>) players.clone();
            for (Entry<String, IPlayer> e : clone.entrySet()) {
                IPlayer p = e.getValue();
                vdata.appendChild(p.writeToXML(doc));
            }




            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer(); // An identity transformer
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(new File("vouchdata.xml"));

            transformer.transform(source, result);
        } catch (TransformerException ex) {
            Logger.getLogger(updateVouchXML.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

特にここでのエラー

BotLinkedMap<String, IPlayer> clone = (BotLinkedMap<String, IPlayer>) players.clone();
        for (Entry<String, IPlayer> e : clone.entrySet()) {
            IPlayer p = e.getValue();
            vdata.appendChild(p.writeToXML(doc));
        }

ボットリンクマップ

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package InHouseLeague.Connections;

import java.util.LinkedHashMap;

/**
*
* @author Mark
*/
public class BotLinkedMap<O1, O2> extends LinkedHashMap<O1, O2> {

    @Override
    public O2 get(Object key) {
        if (key instanceof String) {
            return super.get(((String) key).toLowerCase());
        }

        return super.get(key);
    }

    @Override
    public boolean containsKey(Object key) {
        if (key instanceof String) {
            return super.containsKey(((String) key).toLowerCase());
        }

        return super.containsKey(key);
    }

    @Override
    public O2 remove(Object key) {
        if (key instanceof String) {
            return super.remove(((String) key).toLowerCase());
        }

        return super.remove(key);
    }


    @Override
    public O2 put(O1 key, O2 value) {

        O1 modKey = key;
        O2 modVal = value;

        if (key instanceof String) {
            modKey = (O1) ((String) key).toLowerCase();
        }

        if (value instanceof String) {
            modVal = (O2) ((String) value).toLowerCase();
        }
        return super.put(modKey, modVal);

    }
}

WriteToXML

@Override
public Element writeToXML(Document doc) {
    Element udata = doc.createElement("player");
    try {


        udata.setAttribute("ban", new Long(ban.getDurationMilliseconds()).toString());

        Attr name = doc.createAttribute("name");
        name.setValue(getUserNamePlain());
        udata.setAttributeNode(name);

        Attr qauth = doc.createAttribute("qauth");
        qauth.setValue(getQAUTH().toLowerCase());
        udata.setAttributeNode(qauth);

        Attr rankz = doc.createAttribute("rank");
        rankz.setValue(getRankString().toLowerCase());
        udata.setAttributeNode(rankz);

        Attr vouchedByz = doc.createAttribute("vouchedBy");
        vouchedByz.setValue(getVouchedBy().toLowerCase());
        udata.setAttributeNode(vouchedByz);

        Element eloz = doc.createElement("elo");
        eloz.appendChild(doc.createTextNode(getELO().toString()));
        udata.appendChild(eloz);

        Element matchez = doc.createElement("matches");
        matchez.appendChild(doc.createTextNode(getMatches().toString()));
        udata.appendChild(matchez);

        Element winz = doc.createElement("wins");
        winz.appendChild(doc.createTextNode(getWins().toString()));
        udata.appendChild(winz);

        Element mvpNode = doc.createElement("mvp");
        for (MVP m : getMVP()) {
            mvpNode.appendChild(m.writeToXML(doc));
        }
        udata.appendChild(mvpNode);

        Element truantNode = doc.createElement("truant");
        truantNode.setAttribute("level", new Integer(getTruantCount()).toString());
        for (Truant m : getTruantList()) {
            truantNode.appendChild(m.writeToXML(doc));
        }
        udata.appendChild(truantNode);

        Element history = doc.createElement("history");
        for (GameSummary game : getGameHistory()) {
            history.appendChild(game.writeToXML(doc));
        }

        udata.appendChild(history);
    } catch (Exception ex) {
         udata = doc.createElement("player"); 
    }

    return udata;

}

スタックトレース

Exception in thread "Thread-13" java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:390)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:409)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:408)
at java.util.HashMap.putAllForCreate(HashMap.java:451)
at java.util.HashMap.clone(HashMap.java:682)
at InHouseLeague.Workers.updateVouchXML.run(updateVouchXML.java:55)
at java.lang.Thread.run(Thread.java:722)
4

1 に答える 1

1

ボットリストのクローンを2回作成しているのではないかと疑っています。スレッドを作成したら、

new updateVouchXML((BotLinkedMap<String, IPlayer>)botList.getPlayerData().clone())).start())

もう1回はrun()です。

そして、中間コピーであるthis.playersフィールドは最終的なものではありません。したがって、これはそれらのあいまいな「時期尚早の公開」バグの1つである可能性があります。--this.playersからの2番目のクローンは、this.playersへの1番目のクローンがまだ「進行中」の間に発生しています。

  1. プレイヤーを作ってみてくださいfinal。奇妙なスレッドのバグの問題では、常にできる限りのことをしてくださいfinal
  2. クローンを1回だけ試してください。

私はそれらの1つがそれを修正すると99%確信しています。

他のすべてが失敗した場合は、ConcurrentModificationExceptionをキャッチして、クローンを再試行してください。

于 2013-01-03T05:49:10.953 に答える