2012-02-22 5 views
0

私は長い時間の問題を解決するために多くの方法を検索しますが、方法はまた、私の問題を解決することはできませんので、この問題を解決するためにあなたの助けが必要です、非常に非常にありがとう!update mongoはConcurrentModificationExceptionをスローしますか?

例外スタック:キー

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

更新キー:

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

答えて

1

十分な情報はありませんが、と疑われますあなたのアプリケーションはマルチスレッドであり、現在のスレッドがupdateToMongoを呼び出している間に他のスレッドがBasicDBObjectを更新していると思われます。

これには魔法の解決策はありません。インメモリコピーを永続化している間は、他のスレッドの更新を停止する必要があります。


はい、私のアプリケーションは、マルチスレッド化されますが、新しいクラスでupdateToMongoを呼び出して、すべてのスレッドが、その後、BasicDBObjectはupdateToMongo方法に影響を与えるのだろうか?

updateToMongoへの呼び出しが別のクラスまたは異なるインスタンス内で発生することは関係ありません。別のスレッドが同じインスタンスを保持しようとしている間に、あるスレッドがある特定のBasicDBObjectインスタンスを更新しているので、問題が起きています(私は推測しています)。 (理論的には、これと同じスレッドでも可能ですが、そのシナリオは少し遠いです)

+0

はい、私のアプリケーションはマルチスレッドですが、新しいクラスでupdateToMongoを呼び出すすべてのスレッドは、次にBasicDBObjectがupdateToMongoメソッドに影響しますか?ありがとうございました ! – dawnsky

+0

はい、あなたは正しいです、MongoDatabaseUtilはシングルトンです。そして、私はメソッドupdateToMongoを呼び出すと、collNameを持つDBCollectionを1つだけ取得します – dawnsky

0

for-eachループを使用して、 'points'コレクションを繰り返し処理しています。 アプリケーションがマルチスレッドで、 'points'コレクションを変更(追加、削除など)するとこのエラーが発生します。

あなたには2つのオプションがあります。 まず、通常の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); 
    } 
} 

ラップ同じ同期ブロックに「ポイント」非同期を変更するコード。 また、同じロックオブジェクトを使用して同期することを確認してください。

Iteratorを使用することもできます(まったくお勧めしません)。またはwhileループですが、最終的にはforループと同じことを行い、おそらく効率が低下します。

私は与えられたスタックトレースに正確に従っていませんでしたが、点の更新については何かを言っていますので、私は完全に関係のない資料を投稿しないことを望んでいます。 :)

+0

はい、私は他の応答が正しいと思います。この問題は、スタックトレースからのコードのforループには見えませんが、BasicDBObjectはスレッドセーフではないHashMapから派生しています。 –

+0

@ScottHernandez - スレッドセーフの問題ではありません。 'HashMap'はスレッドセーフである可能性がありますが、反復処理と同時の変更をサポートしていません。 –

+0

@ScottHernandezあなたは正しいかもしれませんが、私はforeachループを使用するときにこの例外をたくさん経験しました。そしてforeachループが彼が提供したコードに含まれていなかったリストを反復していて、それを使って。 –

関連する問題