Return results from executor in java

I need some help retrieving results from executors. The place where I create the workers:

public static void method()
    {
        double bestProb = 0;
        double best p1 = 10000;
        double best p2 = 10000;

        executor = Executors.newFixedThreadPool(5);
        List<Future<Double>> futures = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            double p1 = Math.pow(2, i);
            for (int j = 5; j < 15; j++) {
                double p2 = Math.pow(2, j);
                Callable<Double> worker = new ProbabilityCalculator(p1, p2,);
                futures.add(executor.submit(worker));
                }
            }

        for (Future<Double> future : futures) {
             double prob = future.get();
             prob /= 100;   

                if (prob > bestProb) {
                    bestProb = prob;
                    bestp1 = p1;
                    bestp2 = p2;
                }
}

        System.out.println("Best prob: " + bestProb + ", for: " + bestp1 + ", " + bestp2);
    }

The ProbabilityCalculator class which I want to return a probability that I have to process back in the method with the parameters p1 and p2 that lead to this probability.

public class ProbabilityCalculator implements Callable<Double> {
    private double p1;
    private double p2;
    private double probability;

    private void processCommand() {
     // perform operations
     // here I compute the probability each time
    }          
    public double returnProbability() {
         return this.probability;
    }

    @Override
    public void call() {
        processCommand();
    } 
}
Jon Skeet
people
quotationmark

(This answer was provided when the question was at revision 1. The OP is editing the question in response to the answer, which makes the answer make less sense - rather than me try to keep up with the edits, please refer to revision 1 to see what this was all responding to...)

If you use Callable instead of Runnable, you can use the future returned by the executor to get the return value. If you just want the probabilities, you could use a Callable<Double> like this:

List<Future<Double>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    double p1 = Math.pow(2, i);
    for (int j = 5; j < 15; j++) {
        double p2 = Math.pow(2, j);
        Callable<Double> worker = new ProbabilityCalculator(p1, p2);
        futures.add(executor.submit(worker));           
    }
}
// Do whatever else you want to here...

// Now wait for the results and handle them appropriately.
// Note the exceptions that can be thrown...
for (Future<Double> future : futures) {
    double value = future.get();
    ...
}

The important thing here is that a Runnable doesn't return a value, whereas a Callable does.

As it sounds like you need the p1 and p2 values as well, you should probably encapsulate that in a result type, so you'd implement Callable<ProbabilityResult>, e.g.

public class ProbabilityCalculator implements Callable<ProbabilityResult> {
    private final double p1, p2;

    public ProbabilityCalculator(double p1, double p2) {
        this.p1 = p1;
        this.p2 = p2;
    }

    public ProbabilityResult call() {
        double probabilty = ...;
        return new ProbabilityResult(p1, p2, probability);
    }
}

(Where ProbabilityResult would just be a simple data transfer class, effectively - you could just use a double[] with three values, but that would be fairly unpleasant...)

Now you can use:

double bestProbability = -1;
double bestP1 = 0, bestP2 = 0;
for (Future<ProbabilityResult> future : futures) {
    ProbabilityResult result = future.get();
    if (result.getProbability() > bestProbability) {
        bestProbability = result.getProbability();
        bestP1 = result.getP1();
        bestP2 = result.getP2();
    }
}

Note that I've changed WorkerThread to ProbabilityCalculator - you should not be creating an instance of a subclass of Thread here; the point is for the executor to handle the actual threading; you just provide it the tasks to execute. If your WorkerThread class doesn't actually extend Thread, you should rename it to something less misleading.

people

See more on this question at Stackoverflow