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).
You get what I want. How can I achieve this in Java?
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With