[quote=ViniGodoy]Alguns comentários:
- Aquele while (naoterminou) deve jogar seu processador a 100%. No lugar disso, se quiser esperar as threads, use o método join().
- Você não pode compartilhar variáveis entre threads sem usar sincronização, ou sem que elas sejam volatile;
- É o método update que deveria chamar notifyAll().
- Seria bom criar uma fila e implementar o produtor/consumidor. A thread que monitora a serial é a produta. Ela deve simplesmente ler, capturar o caratere e dispara-lo aos seus listeners. A classe que processa é a consumidora. Ela aguarda uma tecla chegar na fila e a processa. Apenas a fila terá que ser sincronizada, para isso, use uma BlockingQueue. A vantagem é que a própria queue já controla para você os wait, cabendo apenas a você chamar o notifyAll().
Resumindo:
classe ClienteSerial
- Lê uma tecla do cliente;
- Gera um evento de tecla e põe na fila;
- Dá o notifyAll avisando que um novo evento foi colocado
Classe processa serial
- Aguarda um evento entrar na fila (a própria blockingQueue faz o wait);
- Processa esse evento.
- Encaminha o resultado para outra classe (pode ser a iniciaDisplayBD), na forma de mensagens (algo como DisplayArrived, já com o display completamente montado).
Esse seu software é extremamente similar com os que eu trabalhava na época da Siemens. Bateu até saudades.[/quote]
Boa tarde vini,
Dei uma olhada na net, estudei um código que achei e implementei dessa forma:
public class InicialDisplayBO {
private Controller controller;
@SuppressWarnings("unused")
private InicialDisplay inicialDisplay;
public volatile boolean rodando = true;
private BlockingQueue<Integer> fila = new LinkedBlockingDeque<Integer>(10);
private Thread t1;
private Thread t2;
public InicialDisplayBO(InicialDisplay inicialDisplay, Controller controller) {
super();
this.controller = controller;
this.inicialDisplay = inicialDisplay;
t1 = new Thread(new ClienteSerial(fila),"Cliente Serial");
t2 = new Thread(new ProcessaSerial(fila),"Processa Serial");
t2.start();
t1.start();
try {
t2.join();
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void processaTecla(Integer resposta) throws InterruptedException{
char[] caracteres = Character.toChars(resposta.intValue());
System.out.println("Processa Tecla: " + caracteres[0]);
switch(resposta){
case FUNCTION:{
resposta=NUL;
this.controller.setDisplay(Display.SAIR);
this.rodando = false;
}break;
}
}
private class ProcessaSerial implements Runnable{
private Integer resposta;
private BlockingQueue<Integer> fila;
public ProcessaSerial(BlockingQueue<Integer> fila){
this.fila = fila;
}
@Override
public void run() {
while(rodando){
try {
resposta = fila.take();
processaTecla(resposta);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private class ClienteSerial implements Runnable,Observer{
private char resposta=0;
private BlockingQueue<Integer> fila;
private PortaSerial portaSerial = new PortaSerial();
private PortaSerialCOM portaSerialCOM = new PortaSerialCOM();
public ClienteSerial(BlockingQueue<Integer> fila){
this.fila = fila;
portaSerial.setPorta("/dev/ttyS0");
portaSerialCOM.addObserver(this);
try {
portaSerialCOM.abrirPorta(portaSerial);
portaSerialCOM.lerMensagem();
} catch (Exception e) {
e.printStackTrace();
}
}
private void finalizar(){
try {
portaSerialCOM.fecharPorta();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void run() {
while(rodando){
synchronized (this) {
if(resposta==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
finalizar();
}
@Override
public void update(Observable arg0, Object arg1) {
resposta = (Character) arg1;
try {
char tmp = resposta;
fila.put((int) resposta);
resposta=0;
try {
portaSerialCOM.enviarMensagem(tmp);
} catch (Exception e) {
e.printStackTrace();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {
notifyAll();
}
}
}
}
Funcionou!!!
Gostaria de apenas tirar uma dúvida, na thread criada para ouvir a porta serial ( a qual não está nesse meu código ) e que inclusive é uma thread baseada em um artigo aqui do guj
http://javafree.uol.com.br/topic-858960-Protocolo-de-comunicacao-com-API-Javacomm.html ocorre a seguinte situação:
/método RUN da thread de leitura
public void run(){
try {
Thread.sleep(5000);
} catch (Exception e) {
System.out.println("Erro. Status = " + e );
}
}
Ou seja, a thread morre após 5 segundos, não é isso? Mas mesmo assim, ela continua ouvindo a serial por estar na memória, é isso, não é?
A pergunta é: isso é está certo? É assim mesmo, ou foi apenas para fins didáticos?
A outra pergunta é:
No código que postei acima, utilizei as Threads:
t1 = new Thread(new ClienteSerial(fila),"Cliente Serial");
t2 = new Thread(new ProcessaSerial(fila),"Processa Serial");
Posso separá-las dessa classe?
public class InicialDisplayBO {
...
}
A intenção é que outras classes utiliem a leitura e o retorno de caracteres seriais ( ecoem de volta ao equipamento).
Se puder me ajudar com isso tb, mas desde já agradeço imensamente sua ajuda e de todos que de uma forma ou de outra me ajudaram.
Obrigado