Concorrência - Threads

6 respostas
nel

Senhores, bom dia.

Vou explicar minha necessidade.

Tenho uma classe que implementa a interface Runnable que fica consumindo em um loop infinito (while(true)) um serviço.
Quando essa classe recebe uma mensagem, ela alimenta uma determinada lista (a mensagem contém “tipo de mensagem”, e de acordo com esse tipo, ela alimenta uma lista específica.

Então, imaginem assim: listA, listB e listC. Eu tenho outras três classes: classA, classB e classC.
O que eu fiz agora é bem feio (eu sei), fiz uma classe interna para cada classA, classB e classC, cada uma consumindo sua respectiva lista (listA, listB e listC). Qual o problema ? Fica em loop infinito. Imagina o quanto de processador está sendo consumido.

Como não tenho grande experiência com Threads (pois trabalho muito com JEE), qual a sugestão dos senhores para resolver isso com a ideia de uma “flag” ? O eu queria fazer era algo assim: classA aciona o método de uma determinada classe (que popula as três listas que citei acima) e fica esperando por uma resposta, como se tivesse pausado a Thread. Somente quando listA for populada, ela vai devolver uma resposta para classA (isso vale para as outras classes).

Nesse formato, elimino essa implementação ruim e diminuo o consumo do processador.
Peço desculpas pelo texto longo e espero ter sido claro.

Infelizmente, não tenho tempo hábil para alterar tudo, a necessidade é essa e foi feito assim porque estou trabalhando em software de outra pessoa.

Obrigado pessoal. Abraços.

6 Respostas

Ataxexe

Só acho o fato de você trabalhar com JEE não ser motivo para que não conheça as threads.

Além disso, está um pouco confuso. A classe que implementa Runnable consome o serviço e recebe uma mensagem? Vou assumir que a “mensagem recebida” seja a resposta do serviço consumido dentro do loop infinito.

O loop infinito não é bem um problema, é mais ou menos assim que fazemos pooling de dados. O problema é não ter um intervalo entre as checagens, que me parece ser o seu caso. Coloque um intervalo no seu loop pra diminuir o processamento.

Outra coisa: se estiver em um ambiente JEE, evite criar suas threads pois isso leva a muitos problemas (nesse tipo de ambiente, tudo deve ser gerenciado e uma thread sequer terá acesso aos recursos do container). Se for esse o seu caso, procure nas documentações do seu servidor de aplicações sobre como utilizar as threads gerenciadas por ele (os thread pools). Ainda falando em JEE, seu problema parece ser simples de resolver usando JMS.

nel

Ataxexe:
Só acho o fato de você trabalhar com JEE não ser motivo para que não conheça as threads.

Além disso, está um pouco confuso. A classe que implementa Runnable consome o serviço e recebe uma mensagem? Vou assumir que a “mensagem recebida” seja a resposta do serviço consumido dentro do loop infinito.

O loop infinito não é bem um problema, é mais ou menos assim que fazemos pooling de dados. O problema é não ter um intervalo entre as checagens, que me parece ser o seu caso. Coloque um intervalo no seu loop pra diminuir o processamento.

Outra coisa: se estiver em um ambiente JEE, evite criar suas threads pois isso leva a muitos problemas (nesse tipo de ambiente, tudo deve ser gerenciado e uma thread sequer terá acesso aos recursos do container). Se for esse o seu caso, procure nas documentações do seu servidor de aplicações sobre como utilizar as threads gerenciadas por ele (os thread pools). Ainda falando em JEE, seu problema parece ser simples de resolver usando JMS.

Olá Ataxexe, obrigado pelo tempo dispensado.
Me expressei mal, desculpe. Concordo com a primeira afirmação, por trabalhar com JEE acabei focando na especificação e não trabalhei diretamente com Threads, logo, tenho pouco domínio da mesma.

Sobre o meu problema, ele é Java SE “puro”. Não tem servidor de aplicação, container web ou algo do gênero, por isso estou utilizando Threads “na mão”. Em JEE, eu nem cogitaria isso e sim, JMS possivelmente seria a solução.

Agradeceria mais sugestões pensando exclusivamente em um ambiente Java SE.
Forte abraço.

Ataxexe

Será que o intervalo no loop não resolveria seu problema? Algo como um simples Thread.sleep pra começar a testar.

nel

Oi Ataxexe, obrigado novamente.
O problema é que se trata de um jogo de colaboração que antes funcionava em rede local e agora, usando meu middleware, passa a rodar via internet também.

Nesse formato, quando executo uma ação no meu PC (automaticamente, o ambiente é atualizado) você precisa visualizar na sua tela que eu fiz esta ação, para manter ambos ambientes “visualmente iguais”, ou seja, sincronizados. Se eu colocar um delay, posso estar atrasando essa sincronia e perdendo a sincronização das mensagens (posso testar posteriormente, mas entendo que esse é meu maior problema).

Apesar do jogo suportar apenas dois jogadores no momento, a preocupação com a sincronização é a mesma se houvesse mais.
Consegui explicar ?

Obrigado.

Ataxexe

Oi Ataxexe, obrigado novamente.
O problema é que se trata de um jogo de colaboração que antes funcionava em rede local e agora, usando meu middleware, passa a rodar via internet também.

Nesse formato, quando executo uma ação no meu PC (automaticamente, o ambiente é atualizado) você precisa visualizar na sua tela que eu fiz esta ação, para manter ambos ambientes “visualmente iguais”, ou seja, sincronizados. Se eu colocar um delay, posso estar atrasando essa sincronia e perdendo a sincronização das mensagens (posso testar posteriormente, mas entendo que esse é meu maior problema).

Apesar do jogo suportar apenas dois jogadores no momento, a preocupação com a sincronização é a mesma se houvesse mais.
Consegui explicar ?

Obrigado.

Estou começando a entender. Só não entendi muito bem o que seria o seu middleware. Seria a engine do jogo?

Acho que estou fazendo confusão… se você puder explicar o que é mais ou menos o serviço consumido pela classe e a classificação do retorno para as listas…

nel

Oi Ataxexe, obrigado novamente.
O problema é que se trata de um jogo de colaboração que antes funcionava em rede local e agora, usando meu middleware, passa a rodar via internet também.

Nesse formato, quando executo uma ação no meu PC (automaticamente, o ambiente é atualizado) você precisa visualizar na sua tela que eu fiz esta ação, para manter ambos ambientes “visualmente iguais”, ou seja, sincronizados. Se eu colocar um delay, posso estar atrasando essa sincronia e perdendo a sincronização das mensagens (posso testar posteriormente, mas entendo que esse é meu maior problema).

Apesar do jogo suportar apenas dois jogadores no momento, a preocupação com a sincronização é a mesma se houvesse mais.
Consegui explicar ?

Obrigado.

Estou começando a entender. Só não entendi muito bem o que seria o seu middleware. Seria a engine do jogo?

Acho que estou fazendo confusão… se você puder explicar o que é mais ou menos o serviço consumido pela classe e a classificação do retorno para as listas…

Eu só alterei a camada de comunicação do jogo. Por isso eu disse que é praticamente impossível nesse momento alterar toda engine dele para mudar o funcionamento e/ou aplicar melhorias. Ele era RMI e agora tirei o RMI para usar meu middleware.

Vou tentar ilustrar com código o estado atual:

Classe do jogo que consome mensagens do meu middleware.

public class Message implements Runnable {
	
	private static List<Integer> listA = new ArrayList<>();
	
	@Override
	public void run() {
                while (true) {
		   list = ...;
		   for (Integer i : list) {
			if (ehListA)
				listA.add(i);
		   }
                }
	}
	
	public synchronized static Integer getMessage(TipoMSG tipoMSG) {
		if (tipoMSG == A)
			return listA.get(0);
	}

}

classA que pertence ao jogo e consome a mensagem da classe Message.

public class ClassA implements Runnable {
	
	@Override
	public void run() {
                while (true) {
		     Integer i = Message.getMessage(A);
		    //faz algo
                }
	}

}

Explicando dois pontos importantes.

1 ) Tem que ser em Thread separada, caso contrário, o jogo para e/ou sequer inicializa, pois a classeA constrói objetos da cena e etc;

2 ) Usei este método porque antes a interface de comunicação possui uma classe de implementação e outras três classes que extendem ela. Além de ser filha, tem engine do jogo dentro (criar objeto e etc). Usei o tipo de mensagem para identificar para quem está destinada a mensagem. Se é para a classe A, B ou C. Não consegui centralizar tudo porque as classes A, B e C não são instanciadas uma única vez e nem sempre no mesmo lugar, o que me dificultou a vida.

Vou sair nesse momento e retorno assim que puder.
Se quiser, posso enviar uma MP com meu Skype e trocamos uma ideia sobre o problema, ando rachando a cabeça com ele.

Obrigado por tudo.
Abraços.

Criado 20 de março de 2015
Ultima resposta 20 de mar. de 2015
Respostas 6
Participantes 2