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;
}
}
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 ?
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?