0

私は答えを見つけるのに一生懸命探してきましたが、何が間違っているのかわかりません。JAVAスレッドの使い方を学んでいます。事は、私は宇宙船のゲームをやっています. 敵を作成するメソッドが 1 つあります (これらの敵は、動きを効果的にするためにペイントされた ArrayList に追加されます)。この ArrayList で死んだ敵を探す別のメソッドがあります (dead はブール値で、敵が画面から消えた場合、または殺された場合に true になります)。もう描かれません)。createEnemy メソッドを使用するスレッドが 1 つあります (問題なく動作します)。問題が発生しました。この ereaseEnemy メソッドを使用する必要がありますが、同時実行エラーが発生します。両方のメソッドで同期を使用しようとしましたが、ereaseEnemy メソッドが機能しません。これを修正する方法がわかりません。最初のスレッド (クリエーター) を停止して、他のスレッドを機能させますか? ここで何か足りないのですか?ありがとう!

敵を排除するコード

for (Enemigo enemigo1 : enemigos) {
    if (!enemigo1.isEstaVivo()) { enemigos.remove(enemigo1); }
}
4

3 に答える 3

6

あなたは本当に問題のあるコードを投稿する必要がありますが、私は知識に基づいた推測をすることができArrayListますlist.remove(o). スローされる例外はConcurrentModificationException. List.remove()反復中にメソッドを呼び出すことはできません。を使用する必要がありますIterator.remove()。これにより、このユース ケースでは拡張 for ループを使用できなくなります。コードを次のように変更します

for (Iterator<Enemigo> iter = enemigos.iterator(); iter.hasNext();)
  if (!iter.next().isEstaVivo()) iterator.remove();
于 2012-08-26T19:39:27.737 に答える
1

2つの可能な解決策

1)削除する前にリストのコピーを作成します(サイズが大きすぎる場合はパフォーマンスの問題に注意してください)

ArrayList<enemigo> enemigosCopy= new ArrayList<enemigo>(); 
enemigosCopy.addAll(enemigos);
//Do your deleting thing on enemigosCopy

2)イテレータを使用する

 Iterator i =enemigos.iterator();
 while (i.hasNext()) {
   enemigo o = i.next();
   if (!enemigo1.isEstaVivo()) {    
     i.remove(o);      
   }             
 }   
于 2012-08-26T19:49:06.207 に答える
0

自分でスレッドを同期しようとしないでください。java.util.concurrentクラスを使用して、Java に任せてください。あなたの場合、一定のアクセス時間についてはConcurrentLinkedQueueまたはを調べます。ConcurrentMap船の ID をマップのキーとして使用できます。

dead複数のスレッドによってアクセスが正しく処理されるように、敵のフラグの設定を制御する必要があります。データ ストレージはそれを行いません。すべてのスレッドに対してデータ ストアの状態が一貫していることを確認するだけです。

http://docs.oracle.com/javase/6/docs/api/index.html?java/util/concurrent/package-summary.html

于 2012-08-26T19:37:53.293 に答える