GUJ Discussões   :   últimos tópicos   |   categorias   |   GUJ Respostas

Thread em java

Olá, preciso fazer um programa em java que some os 1.000.000 primeiros usando threads.Porém em meu programa cada vez que eu rodo ele dá um resultado diferente.

public class naturais {

public static void main(String[] args) {
	
	Calcular c1 = new Calcular(0,125.000);
	Calcular c2 = new Calcular(126.000,150.000);
	Calcular c3 = new Calcular(151.000,300.000);
	Calcular c4 = new Calcular(301.000,425.000);
	Calcular c5 = new Calcular(426.000,550.000);
	Calcular c6 = new Calcular(551.000,675.000);
	Calcular c7 = new Calcular(676.000,800.000);
	Calcular c8 = new Calcular(801.000,1000.000);

	    c1.start();
	    c2.start();
	    c3.start();
	    c4.start();
	    c5.start();
	    c6.start();
	    c7.start();
	    c8.start();

	
	
	System.out.println("Resultado: " + (c1.getResult() + c2.getResult() +c3.getResult()+ c4.getResult()+c5.getResult() +c6.getResult()+c7.getResult()+ c8.getResult()));
}
	
	
}

public class Calcular extends Thread {

private double vi;
private double vf;
private double result;

public Calcular(double vi, double vf) {
this.vi= vi;
this.vf=vf;


Thread t= new Thread(this);
t.start();


}

@Override
public void run() {
	for(double i = vi; i <= vf; i++) {
        result += i;
	System.out.println(i);
		
	}

}

	

@SuppressWarnings("finally")
public double getResult() {
	  try {
	        this.join();
	    } finally {
	        return result;
	    }
}

}

no construtor vc estarta a Thread e depois no main vc está estartando novamente

2 Curtidas

Ops , nem tinha reparado. Deixei somente a do main porém vejo que está somando várias vezes a mesma sequência de números ,por exemplo de 100.000 a 200.000 mas o resultado pelo menos não está mais mutável. Como resolver isso ?

Se você testa com uma única thread. os resultados saem como você espera em repetidas execuções?

Reparei agora que você está chamando o join na própria classe Calcular.

O método join tem que ser chamado para bloquear até que outra thread finalize sua execução. Portanto você tem que chamar o join na sua main thread

Caso te ajude eu resolvi implementar esse problema por diversão. Ele divide o número total em partes iguais. E o número de partes é o número de threads disponíveis na sua máquina:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

class Serie {
    private Integer valorInicial;
    private Integer valorFinal;

    public Serie(final Integer valorInicial, final Integer valorFinal) {
        this.valorInicial = valorInicial;
        this.valorFinal = valorFinal;
    }

    public Integer getValorInicial() {
        return valorInicial;
    }

    public Integer getValorFinal() {
        return valorFinal;
    }

    @Override
    public String toString() {
        return valorInicial + " ~ " + valorFinal;
    }
}

class Soma extends RecursiveTask<Long> {

    private Integer valorInicial;
    private Integer valorFinal;

    public Soma(final Integer valorInicial, final Integer valorFinal) {
        this.valorInicial = valorInicial;
        this.valorFinal = valorFinal;
    }

    protected Long compute() {
        Long soma = Long.valueOf(0);
        for (int i = valorInicial ; i <= valorFinal ; i++) {
            soma += i;
        }
        return soma;
    }
}

public class Main {

    public static void main(String[] args) {
        int threadsDisponiveis = Runtime.getRuntime().availableProcessors();
        System.out.println("Threads Disponiveis: " + threadsDisponiveis);

        final ForkJoinPool forkJoinPool = new ForkJoinPool(threadsDisponiveis);

        List<Serie> series = montarSeries(1, 1000000, threadsDisponiveis);
        System.out.println(series);
        Long soma = series.stream()
                .map(s -> forkJoinPool.invoke(new Soma(s.getValorInicial(), s.getValorFinal())))
                .mapToLong(Long::longValue)
                .sum();

        System.out.println(soma);
    }

    private static List<Serie> montarSeries(final Integer inicio, final Integer fim, final Integer pedacos) {
        List<Serie> series = new ArrayList<>();
        Integer tamanhoPedaco = fim / pedacos;
        Integer valor = inicio;
        while (valor <= fim) {
            Integer fimPedaco = Math.min(valor + tamanhoPedaco - 1, fim);
            series.add(new Serie(valor, fimPedaco));
            valor = fimPedaco + 1;
        }
        return series;
    }
}

Então , eu só quero que some tudo e dê o resultado certinho. Fiquei confusa sobre o join , eu posso pegar tudo que está em volta dele e colocar no main também ? ou vou ter que criar do 0?

Você só tem que chamar o join na mesma thread que deu o start. Exemplo:

	    c1.start();
	    c2.start();
	    c3.start();
	    c4.start();
	    c5.start();
	    c6.start();
	    c7.start();
	    c8.start();

	    c1.join();
	    c2.join();
	    c3.join();
	    c4.join();
	    c5.join();
	    c6.join();
	    c7.join();
	    c8.join();

Ahhhh entendi , vou tentar fazer aqui.