Executando Threads e seus métodos

3 respostas
J

-Estou fazendo um programa que usa Threads, onde cada uma das Threads tem de executar dois métodos que são o setComprar_reposicao e o Retirar mercadorias uma vez cada método. Mas quando eu executo o progama, o método retirar é realizado somente pela thread que é executada primeiro enquanto que as demais threads executam o método setComprar_reposicao, sendo exibidas somentes estas mensagens que confirmam a sua execução, no seguinte exemplo:

O Funcionario DOIS inseriu a quantidade de 0 itens do produto 3 e a quantidade total em estoque deste produto agora é de 0
O Funcionario UM inseriu a quantidade de 20 itens do produto 2 e a quantidade total em estoque deste produto agora é de 20
O Funcionário DOIS tentou retirar 4 itens, mas a quantidade de 0 itens do produto 3 era insuficiente!
O Funcionario TRES inseriu a quantidade de 62 itens do produto 17 e a quantidade total em estoque deste produto agora é de 62

-O código encontra-se logo abaixo:

public class Tcomercio extends Thread{

	int idcliente;


  private static Mercadoria_a item = new Mercadoria_a();//Instância item do objeto produto que é definido como uma constante

   public Tcomercio(String nome,int cliente)
   {
	   super(nome); //Nome da superclasse construtura
	   this.idcliente=cliente;// identificação do cliente


   }


  public void run()
  {
	 int identificador,quantidade,venda;
	 double valor;

	 quantidade=(int) (Math.random()*100);
	 identificador=(int) (Math.random()*20);
	 valor=(double) (Math.random()*100);
	 venda=(int) (Math.random()*100);

	  item.setComprar_reposicao(identificador, quantidade, valor);

	  item.Retirar(identificador,venda);


  }
	public static void main(String[] args) {


		Tcomercio funcionario1= new Tcomercio("UM",1);
		Tcomercio funcionario2= new Tcomercio("DOIS",2);
		Tcomercio funcionario3= new Tcomercio("TRES",3);

		funcionario1.start();
		funcionario2.start();
		funcionario3.start();

	}

}
/* Fim da classe comercio*/

class Mercadoria_a
{
	int produto_id;
	private int quantidade;
	private double valor;

	private double lucro;
	int quantos;
	double numero;


	private Mercadoria_a produto[]=new Mercadoria_a[20];

	public Mercadoria_a()
	{
		this.quantos=0;

	}
	public synchronized void setComprar_reposicao(int id,int quant,double preco)
	{
		int contador=0,status=0;


	  if(quantos==0)
		{
			  produto[0]=new Mercadoria_a();
			  produto[0].produto_id=id;
			  produto[0].quantidade=quant;
			  produto[0].valor=preco;
			  this.quantos=quantos+1;

			  System.out.println("O Funcionario "+Thread.currentThread().getName()+" inseriu a quantidade de "+quant+" itens do produto "+id+" e a quantidade total em estoque deste produto agora é de "+produto[0].quantidade);
		}

		else if(quantos>0)
				{
				  while(contador<quantos && produto[contador]!=null)
				   {
					  


					  if(produto[contador].produto_id==id)
					  {
					    produto[contador].quantidade=produto[contador].quantidade+quant;

					    System.out.println("O Funcionario "+Thread.currentThread().getName()+" inseriu a quantidade de "+quant+" itens do produto "+id+" e a quantidade total em estoque deste produto agora é de "+produto[contador].quantidade);

					    status=1;


					  }
				      else
				    	 contador++;
				   }
				  
				  if(status==0)
				    {
						  produto[contador+1]=new Mercadoria_a();
						  produto[contador+1].produto_id=id;
						  produto[contador+1].quantidade=produto[contador+1].quantidade+quant;
						  produto[contador+1].valor=preco;

						  System.out.println("O Funcionario "+Thread.currentThread().getName()+" inseriu a quantidade de "+quant+" itens do produto "+id+" e a quantidade total em estoque deste produto agora é de "+produto[contador+1].quantidade);

						  this.quantos=quantos+1;
				    }
		   
		        }
	  
		


	}

	public synchronized void Retirar(int id,int quant)
	{
	 int cont=0;

	  if(quantos<0 )
		  
		System.out.println("O Funcionário "+Thread.currentThread().getName()+" tentou retirar "+quant+" itens do produto "+produto[cont].produto_id+",mas não há nenhum tipo de produto cadastrador ainda!");
	  
	  else
		  while(cont< quantos && produto[cont]!=null)
		   {
				   if(id==produto[cont].produto_id)
				    {
					     if(quant>produto[cont].quantidade)
					      {
						    System.out.println("O Funcionário "+Thread.currentThread().getName()+" tentou retirar "+quant+" itens, mas a quantidade de "+produto[cont].quantidade+" itens do produto "+produto[cont].produto_id+" era insuficiente!");
					      }
					      else
						   {
						     produto[cont].quantidade=produto[cont].quantidade-quant;


						      System.out.println("O Funcionário "+Thread.currentThread().getName()+" vendeu "+quant+" itens do produto "+produto[cont].produto_id+" , " +
								    " deixando uma quantidade de "+produto[cont].quantidade+" itens.");

						      setFechar_caixa(quant,produto[cont].valor);

						    }

				      }
				       cont++;

		     }

  }

  public synchronized void setFechar_caixa(int quant,double preco)
	{
	     numero=quant*preco;
		 this.lucro=lucro+numero;


		System.out.println("O valor do caixa é:"+lucro);
	}

}

3 Respostas

R

Numa análise inicial vejo que seu método main() não está esperando que todas as threads se encerrem. Você pode fazer isso através de um laço de espera ocupada:

while (funcionario1.isAlive() && funcionario2.isAlive() && funcionario3.isAlive()) { // ... Esperar... }

Ou, melhor ainda, criar um pool de threads via Executors.newFixedThreadPool(), submeter essas threads via ExecutorService.execute() e aguardar o encerramento delas via ExecutorService.shutdown():

http://java.sun.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)

T

roger_rf:
Numa análise inicial vejo que seu método main() não está esperando que todas as threads se encerrem. Você pode fazer isso através de um laço de espera ocupada:

while (funcionario1.isAlive() && funcionario2.isAlive() && funcionario3.isAlive()) { // ... Esperar... }

Ou, melhor ainda, criar um pool de threads via Executors.newFixedThreadPool(), submeter essas threads via ExecutorService.execute() e aguardar o encerramento delas via ExecutorService.shutdown():

http://java.sun.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool(int)

Para esperar N threads, deve-se usar o método join, não ficar em espera ocupada. Exemplo:

/**
 * Não é recomendado uma classe estender Thread; deve-se apenas implementar Runnable.
 * A classe abaixo estende Thread apenas como exemplo.
 */
class ThreadExemplo extends Thread {
    public ThreadExemplo (final String msg_, final int ms_) {
        super();
        msg = msg_;
        ms = ms_;
    }
    @Override
    public void run () {
        long t = System.currentTimeMillis();
        try { Thread.sleep (ms); } catch (InterruptedException ex) {}
        System.out.println (msg + " - " + (System.currentTimeMillis() - t) + "ms");
    }
    private String msg;
    private int ms;
}

/**
 * Usando uma classe que implementa Runnable para iniciar uma thread. 
 */
class ThreadCorreta implements Runnable {
    public ThreadCorreta (final String msg_, final int ms_) {
        msg = msg_;
        ms = ms_;
    }
    @Override
    public void run () {
        long t = System.currentTimeMillis();
        try { Thread.sleep (ms); } catch (InterruptedException ex) {}
        System.out.println (msg + " - " + (System.currentTimeMillis() - t) + "ms");
    }
    private String msg;
    private int ms;
}

class TesteJoin {
    
    public static void main(String[] args) {
         ThreadExemplo thr1 = new ThreadExemplo ("Thread 1", 2000);
         ThreadExemplo thr2 = new ThreadExemplo ("Thread 2", 1000);
         Thread thr3 = new Thread (new ThreadCorreta("Thread 3", 1500));
         Thread thr4 = new Thread (new ThreadCorreta("Thread 4", 2500));
         System.out.println ("Iniciando as threads...");
         thr1.start(); thr2.start(); 
         thr3.start(); thr4.start();
         try {
             thr1.join();
             thr2.join();
             thr3.join();
             thr4.join();
         } catch (InterruptedException ex) {
             ex.printStackTrace();
         }
         System.out.println ("Todas as threads foram encerradas com sucesso.");
    }
}
J

-Muito obrigado por sua dica!

-O que você me disse está certo mesmo! pois fazendo as demais threads “dormirem” equanto uma dela é executada ajuda no controle das mesmas.

Criado 30 de junho de 2009
Ultima resposta 1 de jul. de 2009
Respostas 3
Participantes 3