Olá pessoal!!! Preciso da ajuda de vocês para resolver um problema de concorrência que estou tendo aqui no serviço.
Estou fazendo um aplicativo de monitoramento de frente de caixa. Este aplicativo recebe o status dos caixas via socket e guarda as conexões em um HashMap. O aplicativo possui uma thread servidora que recebe as conexões dos caixas e para cada caixa conectado é criada uma nova thread independente que fica trocando os icones dependendo do status. Quando um caixa se desconecta, a thread servidora remove da lista esta conexão só que enquanto isso as outras threads estão lendo a lista procurando cada uma o seu caixa e isso está causando java.util.ConcurrentModificationException Estou com dificuldades para sincronizar o código e não estou conseguindo resolver, se puderem me ajudar, segue abaixo os códigos:
1 - Thread Servidora
public class MonitoringServer extends Thread {
private HashMap<String, PDV> pdvsConectados = new HashMap<String, PDV>();
@Override
public void run() {
ServSocket ss = new ServSocket(4400);
System.out.println("Iniciando Servidor de monitoramento...");
ss.setTimeAlive(10000); // 10 segundos para checagem de conexao
ss.setIgnoreMsgAlive(false);
ss.setIgnoreMsgException(false);
ss.setAutoCriptografia(false);
ss.setAutoCheckSum(false);
ss.start();
System.out.println("Servidor iniciado!");
int contador = 1000;
while (ss.isAlive()) {
try {
Thread.sleep(1);
} catch (Exception e) {
}
if (ss.getBufferSize() > 0) {
receberMensagem(ss);
}
if (--contador == 0) {
contador = 1000;
verificarConexoes(ss);
}
}
System.out.println("Servidor de monitoramento encerrado!");
}
private void verificarConexoes(ServSocket ss) {
ArrayList<String> conexoes = new ArrayList<String>();
System.out.println("PDVs conectados: " + ss.getConnections());
for (int i = 0; i < ss.getConnections(); i++) {
conexoes.add(ss.getConnection(i).getSocket()
.getRemoteSocketAddress().toString());
}
synchronized (pdvsConectados) {
for (String key : pdvsConectados.keySet()) {
String addr = pdvsConectados.get(key).getEndereco();
if (!conexoes.contains(addr)) {
pdvsConectados.remove(key);
}
}
pdvsConectados.notifyAll();
}
}
private void receberMensagem(ServSocket ss) {
PDV pdv = parseMessage(ss.getBufferSocket().getBuffer());
// guardando o endereço IP do pdv
pdv.setEndereco(ss.getBufferSocket().getSocket()
.getRemoteSocketAddress().toString());
// guardando no hash de pdvs
synchronized (pdvsConectados) {
pdvsConectados.put(pdv.toString(), pdv);
pdvsConectados.notifyAll();
}
ss.removeFromBuffer();
}
private PDV parseMessage(String msg) {
/*
* Exemplo 1:1:12 Loja 1 PDV 1 Código da mensagem 12
*/
String[] msgp = msg.split(":");
PDV pdv = new PDV(Integer.parseInt(msgp[0]), Integer.parseInt(msgp[1]),
"F");
// guardando a mensagem do PDV
pdv.setCodigoMensagem(Integer.parseInt(msgp[2]));
return pdv;
}
// este método é acessado por outras Threads, cada uma buscando o seu PDV
public synchronized PDV getPdv(int loja, int codigo) {
synchronized (pdvsConectados) {
try {
// pdvsConectados.wait();
return pdvsConectados.get(new PDV(loja, codigo, "").toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
}
2 - Método run das Threads que acessam a lista
@Override
public void run() {
while (true) {
try {
Thread.sleep(2000);
} catch (Exception e) {
}
// GzMonitoring.SERVER é uma instância da Thread servidora
PDV pdv = GzMonitoring.SERVER.getPdv(loja, codigo);
int message = 0;
try {
message = pdv.getCodigoMensagem();
} catch (Exception e) {
setIcon(iconOffline);
continue;
}
setIcon(MessageCodes.getIcon(message));
}
}
Muito obrigado!