异常堆栈:
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:977)
at java.util.HashMap$KeyIterator.next(HashMap.java:1012)
at org.bson.BSONEncoder.putIterable(BSONEncoder.java:258)
at org.bson.BSONEncoder._putObjectField(BSONEncoder.java:198)
at org.bson.BSONEncoder.putObject(BSONEncoder.java:140)
at org.bson.BSONEncoder._putObjectField(BSONEncoder.java:190)
at org.bson.BSONEncoder.putIterable(BSONEncoder.java:259)
at org.bson.BSONEncoder._putObjectField(BSONEncoder.java:198)
at org.bson.BSONEncoder.putObject(BSONEncoder.java:140)
at org.bson.BSONEncoder._putObjectField(BSONEncoder.java:190)
at org.bson.BSONEncoder.putObject(BSONEncoder.java:140)
at org.bson.BSONEncoder.putObject(BSONEncoder.java:86)
at com.mongodb.OutMessage.putObject(OutMessage.java:190)
at com.mongodb.DBApiLayer$MyCollection.update(DBApiLayer.java:341)
at com.mongodb.DBCollection.update(DBCollection.java:150)
at com.autonavi.sns.util.TileCache.updateToMongo(TileCache.java:589)
at com.autonavi.sns.util.TileCache.updatePoint(TileCache.java:349)
at com.autonavi.sns.workflow.function.UpdatePointFunc.updatePoint(UpdatePointFunc.java:82)
at com.autonavi.sns.workflow.function.UpdatePointFunc.doExec(UpdatePointFunc.java:37)
at com.autonavi.sns.workflow.function.SNSFunction.execFunc(SNSFunction.java:42)
at com.autonavi.sns.workflow.function.SNSFunction.execFunc(SNSFunction.java:45)
at com.autonavi.sns.workflow.function.SNSFunction.execFunc(SNSFunction.java:45)
at com.autonavi.sns.workflow.function.SNSFunction.execFunc(SNSFunction.java:45)
at com.autonavi.sns.workflow.function.SNSFunction.execFunc(SNSFunction.java:45)
at com.autonavi.sns.workflow.SNSWorkFlow.startExec(SNSWorkFlow.java:45)
at com.autonavi.sns.workflow.SNSWorkFlow.execute(SNSWorkFlow.java:31)
at com.autonavi.sns.service.SNSThreadHandler.serviceDispacth(SNSThreadHandler.java:79)
at com.autonavi.sns.service.SNSThreadHandler.run(SNSThreadHandler.java:47)
at java.lang.Thread.run(Thread.java:662)
设置更新密钥:
BasicDBObject udbo = new BasicDBObject();
udbo.put(ConstantUtil.MONGO_ID_KEY, tileId);
List<BasicDBObject> plist = new ArrayList<BasicDBObject>();
for (PointBasic p : points) {
BasicDBObject pkey = new BasicDBObject();
boolean isPhysic = p.isPhysicPoint();
pkey.put("isphysic", isPhysic);
pkey.put("x", p.getX());
pkey.put("y", p.getY());
pkey.put("picurl", p.getPicUrl());
pkey.put("area", p.getArea());
plist.add(pkey);
}
BasicDBObject pdbo = new BasicDBObject();
pdbo.put("$set", new BasicDBObject("point", plist));
return this.updateToMongo(udbo, pdbo, TILE_LAYER);
更新mongo的密钥:
private boolean updateToMongo(BasicDBObject udbo, BasicDBObject ukey, long layer) {
boolean flag = false;
try {
this.mongo = MongoDatabaseUtil.getInstance();
this.coll = mongo.getCollection(ConstantUtil.TILE_COLL + layer);
this.coll.update(udbo, ukey, true, true);
flag = true;
} catch (MongoException e) {
LOG.error("Mongo error : ", e);
}
return flag;
}
答案 0 :(得分:1)
没有足够的信息可以确定,但我怀疑您的应用程序是多线程的,并且当前线程正在调用BasicDBObject
时,其他一些线程正在更新updateToMongo
updateToMongo
1}}。
这没有神奇的解决方案。在持久化时,必须阻止其他线程更新内存中的副本。
是的,我的应用程序是多线程的,但是每个线程在一个新类中调用updateToMongo,那么BasicDBObject会影响updateToMongo方法吗?
我不认为对BasicDBObject
的调用发生在“不同的类或不同的实例中”是相关的。问题正在发生(我猜)因为一个线程正在更新给定的{{1}}实例,而另一个线程正在尝试持久保存同一个实例。 (理论上它甚至可能是同一个线程这样做......但这种情况有点牵强。)
答案 1 :(得分:0)
你正在使用for-each循环迭代你的'points'集合。 如果您的应用程序是多线程的,并且您修改(添加,删除等)'points'集合,您将收到此错误。
你有几个选择。 首先,是使用常规for循环并使用当前索引检索对象。
for (int i = 0; i < points.size(); i++) {
PointBasic p = points.get(i); // could be different depending upon your collection type.
...
}
但是,如果您在迭代时修改了点集合,则可能会跳过一些数据而您不会知道它:O
如果此操作是强制性的,则尝试同步代码
(同步代码可确保包含在同一块中的代码永远不会跨线程同时执行。)
<global>
private Object pointsLock = new Object();
</global>
synchronized (pointsLock) {
for (PointBasic p : points) {
BasicDBObject pkey = new BasicDBObject();
boolean isPhysic = p.isPhysicPoint();
pkey.put("isphysic", isPhysic);
pkey.put("x", p.getX());
pkey.put("y", p.getY());
pkey.put("picurl", p.getPicUrl());
pkey.put("area", p.getArea());
plist.add(pkey);
}
}
在同一个同步块中包装修改“points”异步的任何代码。 另外,请确保使用相同的锁定对象进行同步。
您也可以使用Iterator(根本不推荐)或while循环,但最后它们与for循环的作用大致相同,可能效率较低。
我没有完全按照给出的堆栈跟踪,但它确实说了一些关于更新点的事情,所以我希望我没有发布完全不相关的材料。 :)