Como lido com essa exceção:

19 respostas
nissivm

Obs.: Não postei as classes porque elas requisitam muitas imagens e eu teria que postar todas para as classes rodarem corretamente.

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
	at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
	at java.util.AbstractList$Itr.next(Unknown Source)
	at caça_ao_tesouro.Jogo$botaoEncontrarListener.actionPerformed(Jogo.java:191)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.awt.EventQueue.access$000(Unknown Source)
	at java.awt.EventQueue$1.run(Unknown Source)
	at java.awt.EventQueue$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
	at java.awt.EventQueue$2.run(Unknown Source)
	at java.awt.EventQueue$2.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

19 Respostas

nel

Oi!

Podes usar a classe Collections para lidar com esse problema.
O que pode estar ocorrendo é que um método você remove o objeto da posição 0 e no outro você altere ele, por exemplo.

Se for uma lista, podes usar o método synchronizedList, que dita que o acesso a lista será “uma thread de cada vez”. Isso garante a integridade das informações.

Abraços.

R
at caça_ao_tesouro.Jogo$botaoEncontrarListener.actionPerformed(Jogo.java:191)

Coloca esse código aqui.

nel

Por isso eu passei o Javadoc :smiley:

nissivm

Oi gente, não dei um feedback ainda pq estou tendo algumas problemas com esse app que estou fazendo…

Aliás, exemplo(ilustra um dos meus problemas):

Digamos que eu tenho 10 objetos da classe pessoa, certo? Eu quero dar um nome para cada pessoa, sendo que esses nomes estão dentro de um ArrayList. Eu não quero dar o mesmo nome para 2 ou + pessoas. Como vcs fariam?

nel

Sim, imaginei isso. Mas esse é um tipo de ponto que prefiro indicar mais explicitamente :)

Perfeito Wellington, foi muito bem salientado :slight_smile:

nissivm

Só falta resolver essa exceção: [color=red]ConcurrentModificationException[/color], parece que isso acontece quando vc tenta fazer duas modificações diferentes numa mesma lista e ao mesmo tempo. Não consegui identificar, talvez os olhos experientes de vcs consigam. Aí abaixo está o bloco de código que contém a linha apontada no problema(8):

class botaoEncontrarListener implements ActionListener {		
		public void actionPerformed(ActionEvent arg0) {
			
			String userGuess = txtCodigo.getText().toUpperCase();
			String result = "No chest found, keep looking";
			txtCodigo.setText("");
			
			for(Arcas arcaTest : arcasList){ //É como se arcaTest se tornasse um dos obj. de arcasList, o que acontece a um é como se acontecesse ao outro
								
				if(userGuess.equals(arcaTest.getPosition())){
					
					result = arcaTest.checkResult(arcaTest.getName());
					numCoins += arcaTest.getCoins();
					++numOfFoundChests;
					
					try {
						image = ImageIO.read(new File("C:\Users\Nissi\Documents\Docum_Nissi\Eclipse_JSE_Helios_Workspace\Meus Aplicativos Java\Caça_ao_Tesouro\imagens\ImgInstrucoes.bmp"));
						image2 = ImageIO.read(mapas[numOfFoundChests]);
					} catch (IOException e) {				
						e.printStackTrace();
					}
			        			        					
					int w = image2.getWidth();   
					int h = image2.getHeight();
					
					Graphics2D graphics = image.createGraphics();  
					graphics.drawImage(image2, 130, 5, w, h, null);
					graphics.dispose(); //Libera os recursos ocupados pela "Caneta"
					
					ImageIcon icon = new ImageIcon(image);			
					lblMainImage.setIcon(icon);
					
					lblMainImage.setBounds(0, 0, image.getWidth(), image.getHeight());
					
					painel.add(lblMainImage);
					
					arcasList.remove(arcaTest);
					
					lblmsg.setText(result);
					
					String quantMoedas = Integer.toString(numCoins);
					lblnumMoedas.setText("You won " + quantMoedas + " golden coins!");
															
				}else{									
					lblmsg.setText(result);										
				}
				
				if(arcasList.isEmpty()){
					finishGame();
					break;
				}
			}			
		}		
	}
pmlm
nissivm:
for(Arcas arcaTest : arcasList){ 
								
	(...)
					
		        	arcasList.remove(arcaTest);

O teu problema está aqui. Não podes remover um objecto de uma lista que estás a percorrer. Usa Iterator

Iterator<Arcas> it = arcasList.iterator();

while(it.hasNext()){
     Arcas arcaTest = it.next();

(...)								
     it.remove();
nissivm

Não deu certo, :frowning: … Ficou aparecendo linhas vermelhas embaixo das coisas e no fim ele disse que não podia converter de void para boolean, de Arcas para boolean… Tem problema não fazer nada em relação a essa exceção? O programa está funcionando direitinho mesmo com ela… Tem como jogar essa exceção para outro método?

nel

É uma péssima pratica tentar resolver o problema dessa forma.
Como foi dito, você está iterando sobre uma lista e ao mesmo tempo tenta remover um objeto dela, não faça isso.

Só um detalhe sobre sua lógica, é totalmente desnecessário remover um objeto da lista e posteriormente verificar se a lista é vaziar para dar o break.
Veja bem, o foreach vai percorrer toda a sua lista, até que não contenha mais nenhum objeto. Se não entrar na sua condição para remoção, ele vai executar o else e partir para o próximo objeto de qualquer forma.

Sendo assim, tem coisa desnecessário em seu código e causando erro. Retire as linhas:

arcasList.remove(arcaTest);
//e a linha
if(arcasList.isEmpty()){  
                    finishGame();  
                    break;  
                }

Se realmente precisas desse finishGame, procure outra lógica, mude para vetor, enfim, altere o seu código.
Abraços.

nissivm

Deixa eu explicar: Eu criei 10 objetos da classe Arcas e coloquei eles num ArrayList(arcasList). Cada objeto tem um código, a posição, simbolizado por uma letra e um número. Quando o usuário coloca uma letra e um numero e clica no botão para ver se encontrou a localização de alguma arca, o for vai percorrer todo o arraylist e, se encontrar uma arca cuja posição seja igual ao que o usuário colocou, ele exclui essa arca do arraylist, já que ela foi encontrada.

De qq forma, vou tentar não usar nenhuma iteração, já que está dando problema. Na verdade, essa idéia do for eu tirei do jogo sinkADotCom, que tem no Head First Java, se fiz bobagem, peço desculpas :oops: , é que sou iniciante em Java(começei a menos de 2 meses atrás rs, não sabia de absolutamente nada…). Mas tenho aprendido muito, inclusive com esse fórum :slight_smile: . Se vc tiver alguma sugestão em código para mim com certeza vou testar nel, quero muito aprender :slight_smile: .

Obrigada por ter respondido! Abraços.

ViniGodoy

Você deve usar o iterator(), como foi dito. Ele suporta remoção durante a iteração.

Agora, você está usando Java anterior a versão 5? Ou seria J2ME?

ViniGodoy
Seu mesmo código com iterator:
class botaoEncontrarListener implements ActionListener {		
		public void actionPerformed(ActionEvent arg0) {
			
			String userGuess = txtCodigo.getText().toUpperCase();
			String result = "No chest found, keep looking";
			txtCodigo.setText("");

			Iterator<Arcas> it = arcasList.iterator();			
			while (it.hasNext()) {
				Arcas arcaTest = it.next();				
				if(userGuess.equals(arcaTest.getPosition())){
					
					result = arcaTest.checkResult(arcaTest.getName());
					numCoins += arcaTest.getCoins();
					++numOfFoundChests;
					
					try {
						image = ImageIO.read(new File("C:\Users\Nissi\Documents\Docum_Nissi\Eclipse_JSE_Helios_Workspace\Meus Aplicativos Java\Caça_ao_Tesouro\imagens\ImgInstrucoes.bmp"));
						image2 = ImageIO.read(mapas[numOfFoundChests]);
					} catch (IOException e) {				
						e.printStackTrace();
					}
			        			        					
					int w = image2.getWidth();   
					int h = image2.getHeight();
					
					Graphics2D graphics = image.createGraphics();  
					graphics.drawImage(image2, 130, 5, w, h, null);
					graphics.dispose(); //Libera os recursos ocupados pela "Caneta"
					
					ImageIcon icon = new ImageIcon(image);			
					lblMainImage.setIcon(icon);
					
					lblMainImage.setBounds(0, 0, image.getWidth(), image.getHeight());
					
					painel.add(lblMainImage);
					
					it.remove();
					lblmsg.setText(result);
					
					String quantMoedas = Integer.toString(numCoins);
					lblnumMoedas.setText("You won " + quantMoedas + " golden coins!");
															
				}else{									
					lblmsg.setText(result);										
				}
				
				if(arcasList.isEmpty()){
					finishGame();
					break;
				}
			}			
		}		
	}
nissivm

Oi Vini, estou usando a versão 5, mas eu já consegui resolver o problema, dei um jeito de remover elementos do ArrayList fora do for, aí deu certo.

Aproveitando, eu tenho uma pergunta sobre um outro assunto: Como inserir som (música de jogo), que começe a tocar assim que o usuário abra o aplicativo? E depois, como interrompe-la?

Obrigada pela atenção :slight_smile:

nel

nissivm:
Oi Vini, estou usando a versão 5, mas eu já consegui resolver o problema, dei um jeito de remover elementos do ArrayList fora do for, aí deu certo.

Aproveitando, eu tenho uma pergunta sobre um outro assunto: Como inserir som (música de jogo), que começe a tocar assim que o usuário abra o aplicativo? E depois, como interrompe-la?

Obrigada pela atenção :slight_smile:

Oi nissi!
O ideal é que edite o seu tópico e adicione [Resolvido] ao fim dele. Em seguida, abre um novo tópico com a sua dúvida e não esquece de explicar se é Mobile, Web, Desktop, são informações importante e para cada item que citei, tem um local reservado no fórum ok?

Sucesso!

nissivm

Ah, tá ok.

[resolvido]

ViniGodoy

Na verdade, a explicação de mobile, interface gráfica, etc. poderia ser dada se você abrisse o tópico no fórum correto. Você abriu em “java básico”, que geralmente refere-se a sintaxe básica da linguagem. Como seu tópico envolve swing, seria interessante abri-lo em interface gráfica. Note que temos um fórum também para J2ME, JavaEE e Outras linguagens.

Não é trivial tocar sons em Java. Eu usaria uma biblioteca pronta, como a JavaZoom. A api de som do java, javax.sound, é de baixo nível, e exija que vc conheça detalhes demais sobre o arquivo de áudio.

WellingtonRamos

nel:
Oi!

Podes usar a classe Collections para lidar com esse problema.
O que pode estar ocorrendo é que um método você remove o objeto da posição 0 e no outro você altere ele, por exemplo.

Se for uma lista, podes usar o método synchronizedList, que dita que o acesso a lista será “uma thread de cada vez”. Isso garante a integridade das informações.

Abraços.


Há uma informação muito importante no JavaDoc que não deve ser negligenciada:

“JavaDoc”:
It is imperative that the user manually synchronize on the returned list when iterating over it:

List list = Collections.synchronizedList(new ArrayList()); ... synchronized(list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }


A iteração não será síncrona, mesmo utilizando uma lista síncrona. Cuidado com esse ponto

WellingtonRamos

Sim, imaginei isso. Mas esse é um tipo de ponto que prefiro indicar mais explicitamente :slight_smile:

WellingtonRamos

nissivm:
Oi gente, não dei um feedback ainda pq estou tendo algumas problemas com esse app que estou fazendo…

Aliás, exemplo(ilustra um dos meus problemas):

Digamos que eu tenho 10 objetos da classe pessoa, certo? Eu quero dar um nome para cada pessoa, sendo que esses nomes estão dentro de um ArrayList. Eu não quero dar o mesmo nome para 2 ou + pessoas. Como vcs fariam?


De onde virá a lista de nomes?
Só isso pode mudar totalmente a lógica.
De qualquer forma, um for deveria resolver razoavelmente seu problema.

Criado 20 de junho de 2011
Ultima resposta 20 de jun. de 2011
Respostas 19
Participantes 6