Paralelní výpočty pomocí Future
- obecně
- výpočet je rozdělen na úlohy (task)
- úlohy jsou předány executorovi, který je postupně vykonává
- typicky určíme, kolik úloh může být maximálně zpracováno paralelně
- po odeslání úlohy obdržíme tzv. future (též promise)
- reprezentuje výsledek
- metoda
get
nám výsledek sdělí (popř. na něj počká)
- dokumentace
- typicky vytvoříme vlastní třídu, která implementuje
Callable
- podobně jako u kolekcí je typovaná typem výsledku
- využijeme třídu
Executors
pro vytvoření správce úloh
- např.
newFixedThreadPool
vytvoří tzv. pool 2 vláken, která budou postupně úlohu řešit
Příklad: paralelní výpočet prvočísel
import java.math.BigInteger;
public class IsPrime {
private static final BigInteger BIG_TWO = new BigInteger("2");
private static final BigInteger BIG_THREE = new BigInteger("3");
public static boolean isPrime(BigInteger number) {
if (number.compareTo(BigInteger.ONE) <= 0) {
return false;
}
if (number.compareTo(BIG_THREE) <= 0) {
return true;
}
if (number.remainder(BIG_TWO).equals(BigInteger.ZERO)) {
return false;
}
BigInteger div = BIG_THREE;
while (div.compareTo(number) < 0) {
if (number.remainder(div).equals(BigInteger.ZERO)) {
return false;
}
div = div.add(BIG_TWO);
}
return true;
}
public static void main(String[] args) {
long start = System.nanoTime();
for (String arg : args) {
BigInteger num = new BigInteger(arg);
System.out.printf("%s => %s\n", num, isPrime(num));
}
long end = System.nanoTime();
long diff = end - start;
System.out.printf("[%dns (%dms)]\n", end - start, (end - start) / 1000 / 1000);
}
}
import java.math.BigInteger;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
public class IsPrimeFuture {
private static final BigInteger BIG_TWO = new BigInteger("2");
private static final BigInteger BIG_THREE = new BigInteger("3");
private static class IsPrimeComputation implements Callable<Boolean> {
private BigInteger number;
public IsPrimeComputation(BigInteger num) {
number = num;
}
@Override
public Boolean call() {
if (number.compareTo(BigInteger.ONE) <= 0) {
return false;
}
if (number.compareTo(BIG_THREE) <= 0) {
return true;
}
if (number.remainder(BIG_TWO).equals(BigInteger.ZERO)) {
return false;
}
BigInteger div = BIG_THREE;
while (div.compareTo(number) < 0) {
if (number.remainder(div).equals(BigInteger.ZERO)) {
return false;
}
div = div.add(BIG_TWO);
}
return true;
}
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
int cpus = Runtime.getRuntime().availableProcessors();
System.out.printf("Have %d CPUs.\n", cpus);
ExecutorService exec = Executors.newFixedThreadPool(cpus);
List<Future<Boolean>> results = new ArrayList<>();
long start = System.nanoTime();
for (String arg : args) {
BigInteger num = new BigInteger(arg);
results.add(exec.submit(new IsPrimeComputation(num)));
}
for (int i = 0; i < args.length; i++) {
System.out.printf("%s => %s\n", args[i], results.get(i).get());
}
long end = System.nanoTime();
long diff = end - start;
System.out.printf("[%dns (%dms)]\n", end - start, (end - start) / 1000 / 1000);
exec.shutdown();
}
}