pmichna
pmichna

Reputation: 4888

How to pass a parameter to a thread and get a return value?

How to pass a parameter to a thread and get a return value?

public class CalculationThread implements Runnable {

    int input;
    int output;
    
    public CalculationThread(int input)
    {
        this.input = input;
    }
    
    public void run() {
        output = input + 1;
    }
    
    public int getResult() {
        return output;
    }
}

Somewhere else:

Thread thread = new Thread(new CalculationThread(1));
thread.start();
int result = thread.getResult();

Of course, thread.getResult() doesn't work (it tries to invoke this method from the Thread class).

How can I achieve this in Java?

Upvotes: 8

Views: 31373

Answers (5)

Andrey Chaschev
Andrey Chaschev

Reputation: 16486

This a job for thread pools. You need to create a Callable<R> which is Runnable returning a value and send it to a thread pool.

The result of this operation is a Future<R> which is a pointer to this job which will contain a value of the computation, or will not if the job fails.

public static class CalculationJob implements Callable<Integer> {
    int input;

    public CalculationJob(int input) {
        this.input = input;
    }

    @Override
    public Integer call() throws Exception {
        return input + 1;
    }
}

public static void main(String[] args) throws InterruptedException {
    ExecutorService executorService = Executors.newFixedThreadPool(4);

    Future<Integer> result = executorService.submit(new CalculationJob(3));

    try {
        Integer integer = result.get(10, TimeUnit.MILLISECONDS);
        System.out.println("result: " + integer);
    } catch (Exception e) {
        // interrupts if there is any possible error
        result.cancel(true);
    }

    executorService.shutdown();
    executorService.awaitTermination(1, TimeUnit.SECONDS);
}

Prints:

result: 4

Upvotes: 19

Georgy Gobozov
Georgy Gobozov

Reputation: 13731

Old school style

public class CalculationThread extends Thread {

    int input;
    int output;

    public CalculationThread(int input){
        this.input = input;
    }

    public void run() {
        output = input + 1;
    }

    public int getResult() {
        return output;
    }
}

CalculationThread thread = new CalculationThread(1);
thread.start();
thread.join();
int result = thread.getResult();

Upvotes: 3

bowmore
bowmore

Reputation: 11280

The accepted answer is great. But it is not the simplest approach. There's no real need to use an ExecutorService if you just want to wait for the result of a thread. You can simply use java.util.concurrent.FutureTask, which is basically a Runnable wrapping a Callable which also implements the Future interface.

So step 1 is still make the calculation a Callable :

public class Calculation implements Callable<Integer> {

    private final int input;

    public Calculation(int input) {
        this.input = input;
    }

    @Override
    public Integer call() throws Exception {
        return input + 1;
    }
}

So where you need the asynchronous calculation you can do :

    FutureTask<Integer> task = new FutureTask<>(new Calculation(1561));
    new Thread(task).start();

    // ... do other stuff

    // when I really need the result :

    try {
        int result = task.get(); // this will wait for the task to finish, if it hasn't yet.
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } catch (ExecutionException e) {
        e.getCause().printStackTrace(); // e.getCause() holds the exception that happened on the calculation thread
    }

What the ExecutorService adds is managing a pool of threads to run the task on, but under the hood of an ExecutorService, basically the same thing happens.

Upvotes: 6

Roman C
Roman C

Reputation: 1

Use constructor and pass value by reference.

public CalculationThread(int[] input)

Do you want to pass the value of int to the thread called CalculationThread you should create a thread but if you pass a parameter by value the thread can use that value but you can't get the data back. Passing it by reference you can modify the value but not reference in the thread and the reference if it's available to both threads point to the value which is modifiable in both threads. Of cause you code should be synchronized to share the same reference.

Upvotes: 0

Silviu Burcea
Silviu Burcea

Reputation: 5348

You are looking for Callable. It's a Runnable on steroids, it can return a result. Check the javadoc:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Callable.html

Here is a tutorial: http://www.journaldev.com/1090/java-callable-future-example

Upvotes: 5

Related Questions