Problemas ao usar o wait ();

Galera, estou fazendo um jogo da memória. Estava com problema em deixar imagens clicadas à mostra. Estava usando o Thread.sleep(); mas tava dando problema. Resolvi tentar usar o wait(); ta funcionando de boa, mas no eclipse ocorre o seguinte erro:

Exception in thread “AWT-EventQueue-0” java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at Memoria2$TratarEventos.actionPerformed(Memoria2.java:84)
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.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)

o código é esse:

public void actionPerformed (ActionEvent evento) { for (int i = 0; i < botao.length; i++) { if (evento.getSource() == botao[i]) { botao[i].setIcon(icones[i]); temp = new Timer (2500, this); temp.start(); if (but1 ==-1) { but1 = i; jogada++; } else { but2 = i; jogada++; } try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } }

Pelo que percebi, o wait () se refere ao Timer, correto?

O método wait() deve ser chamado dentro de um contexto sincronizado, isto é:

synchronized(this){
  try{
   this.wait();
 }catch(InterruptedException ie){}
}

Isto ocorre porque um Thread não pode chamar um método wait() de um objeto a menos que obtenha o bloqueio desse objeto.

Com esse código o programa executa e trava.

Oi,

Você está utilizando o interrupted em algum lugar?

Tchauzin!

não

wait e notify não devem ser chamados se você não souber exatamente o que está fazendo.
São primitivas muito arriscadas se você não souber usá-las direito (threads, wait e notify são o equivalente do “goto” em programação estruturada).
Normalmente, você deve evitar usar tais coisas, e usar rotinas do pacote java.util.concurrent.

Eis aí o código na integra:

[code]import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.Timer;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JPanel;
import javax.swing.ImageIcon;
import java.util.Random;
import javax.swing.JOptionPane;
public class Memoria2 extends JFrame {
JButton [] botao;
ImageIcon [] icones;
ImageIcon padrao;
Random r = new Random();
JButton memoria;
Timer temp;
public Memoria2 (int quant,int t1, int t2 , int h, int l) {
super (“Jogo da Memória”);
icones = new ImageIcon[quant];
Random r = new Random();
padrao = new ImageIcon(this.getClass().getResource(“img/pokebola.gif”));
padrao.setImage(padrao.getImage().getScaledInstance(110, 114, 200));
botao = new JButton[quant];
setIconImage(padrao.getImage());
for (int i = 0; i < ((botao.length)/2); i++) {
String aux=“img/”+Integer.toString(i)+".gif";
icones[i] = new ImageIcon(this.getClass().getResource(aux));
icones[i].setImage(icones[i].getImage().getScaledInstance(110, 114, 200));
}
for (int i = (botao.length)/2; i < botao.length; i++) {
icones[i] = icones[i-((botao.length)/2)];
}
for (int i = 0; i < botao.length; i++) {
int pos = r.nextInt(botao.length);
ImageIcon img = icones[i];
icones[i] = icones[pos];
icones[pos] = img;
}
for (int i = 0; i < botao.length; i++) {
botao[i] = new JButton(padrao);
}
setLayout (new BorderLayout());
JPanel panel = new JPanel();
panel.setLayout(new GridLayout (t1,t2,0,0));
for (int i = 0; i < botao.length; i++){
panel.add(botao[i]);
}
add(panel,BorderLayout.CENTER);
TratarEventos te = new TratarEventos ();
for (int i = 0; i < botao.length; i++) {
botao[i].addActionListener(te);
}
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setSize(h,l);
setResizable(false);
setLocationRelativeTo(null);
setVisible(true);
}
public void resetarImagens(int a, int b) {
botao[a].setIcon(padrao);
botao[b].setIcon(padrao);
}
private class TratarEventos implements ActionListener {
int jogada;
int but1, but2, fim;
public void actionPerformed (ActionEvent evento) {
for (int i = 0; i < botao.length; i++) {
if (evento.getSource() == botao[i]) {
botao[i].setIcon(icones[i]);
temp = new Timer (1000, this);
temp.start();
if (but1 ==-1) {
but1 = i;
jogada++;
}
else {
but2 = i;
jogada++;
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}

			}
		}
		if (jogada == 2) {
			if (but1 == but2) {
				resetarImagens(but1, but2);
				but1 = -1;
				but2 = -1;
				jogada = 0;
			}
			else 
				if (botao[but1].getIcon() != botao[but2].getIcon()) {
					resetarImagens(but1, but2);
					but1 = -1;
					but2 = -1;
					jogada = 0;
				}
				else {
					botao[but1].setEnabled(false);
					botao[but2].setEnabled(false);
					fim +=2; 
					but1 = -1;
					but2 = -1;
					jogada = 0;
				}
		}
		if (fim == botao.length)
			JOptionPane.showMessageDialog(null, "Fim de Jogo!", 
			"Fim de Jogo", JOptionPane.INFORMATION_MESSAGE);
	}
}
public static void main(String[] args) {
	String op = JOptionPane.showInputDialog ("Informe o grau de dificuldade: " +
			""+"\n 1 - Fácil"+"\n 2 - Médio"+"\n 3 - Dificil");
	if (op.equals("1"))
		new Memoria2(20, 4,5, 600, 520);
	else if (op.equals("2"))
		new Memoria2(30, 5,6, 710, 630);
	else if (op.equals("3"))
		new Memoria2(40, 5,8,920,630);
}

}

[/code]

Se alguem puder testar meu código, eu agradeço
(trocar o caminho da imagem)

[quote=entanglement]wait e notify não devem ser chamados se você não souber exatamente o que está fazendo.
São primitivas muito arriscadas se você não souber usá-las direito (threads, wait e notify são o equivalente do “goto” em programação estruturada).
Normalmente, você deve evitar usar tais coisas, e usar rotinas do pacote java.util.concurrent. [/quote]

Oi,

Acho que não é bem assim né!

Tchauzin!

Toda vez que achei código com wait e notify para fazer manutenção, vi que havia algum problema de implementação (já que é uma arte conseguir usar adequadamente tais métodos), e que as coisas poderiam ser feitas de maneira mais simples usando-se algum conceito de nível mais alto, implementado em alguma classe de java.util.concurrent.

Ao chamar wait(), o Thread libera os bloqueios do objeto e aguarda eternamente até que uma chamada notify ou notifyAll seja feita no objeto monitor. Ao ver superficialmente o seu código, vi que você fez uma chamada wait() para aguardar até que uma determinada operação ou método sejam realizados. Assim, você deve notificar o Thread que está aguardando, com uma chamada notify() ou notifyAll() imediatamente após o termino da última linha de instrução do método ou operação a serem executados.