I believe am getting bad data because the instance variable are not thread safe.
I am trying to use multi-threading in a way that opens (at most) 13 threads at a time based on a list. I am using it in a service and need to pass parameters into the run method, so I made some instance variables and set them. I also want those thirteen methods to execute before moving on to the next iteration of the first for loop
private EnergyPortalGroup superGroup;
private EnergyPortalSubGroups singleSubGroup;
private BillingPeriod singlePeriod;
private DateTime[] dateTimeArray;
private void parseGroup(EnergyPortalGroup superGroup) throws InterruptedException{
EnergyPortalSubGroupsCriteria criteria = new EnergyPortalSubGroupsCriteria();
criteria.setGroupId(superGroup.getId());
List<EnergyPortalSubGroups> wholeSubGroupList = subgroupsFactory.readList(criteria);
for (EnergyPortalSubGroups singleSubGroup : wholeSubGroupList){
this.singleSubGroup = singleSubGroup;
this.deleteSubGroupRecordsFromDB(singleSubGroup);
List<BillingPeriod> billingPeriodList = this.getPreviousTwelveBillingPeriods(singleSubGroup, superGroup);
if (billingPeriodList != null && billingPeriodList.size() > 0){
Thread[] threads = new Thread[billingPeriodList.size()];
for (int i = 0; i < billingPeriodList.size(); i++){
this.singlePeriod = billingPeriodList.get(i);
threads[i] = new Thread(this);
threads[i].start();
}
for (Thread thread : threads){
thread.join();
}
}
}
}
Here is my overridden run method:
#Override
public void run(){
List<GroupSummarization> groupSummarizationsToWriteList = new ArrayList<>();
WidgetDataSummationHolder holder = new WidgetDataSummationHolder();
holder = energyPortalService.getEnergyPortalWidgetsSummedData(singleSubGroup, null, null, singlePeriod);
parseSummationHolder(groupSummarizationsToWriteList, holder, singleSubGroup, dateTimeArray, singlePeriod);
processBatchLists(groupSummarizationsToWriteList, superGroup, singlePeriod);
}
Can anyone help me make this thread safe? I am obviously new to multithreading and I tried passing these variables in with a constructor but I have some autowired services that were null and I was getting a null pointer at this line holder = energyPortalService.getEnergyPortalWidgetsSummedData(singleSubGroup, null, null, singlePeriod);
energyPortalService cannot be null sometimes and not other times, given the code you provided. If it is not null when you launch a new Thread(this), then it should be there if you would use a new Thread(()-> {...});
(since you are talking about autowiring, I will presume a whole lot of foul play can occur with osgi and aop and such evils.)
In the end, I went with ExecutorService and a new class/service like a few suggested. So here is an example in case anyone else runs into this type of problem:
for (final Object x : list){
List<Object> someList = getList();
if (!Collections.isEmpty(someList)){
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<?>> futures = new ArrayList<Future<?>>();
for (final Object n : someList){
futures.add(executorService.submit(new Runnable(){
#Override
public void run(){
someOtherService.process(parameters)
}
}));
}
for (Future<?> f : futures){
try {
f.get();
} catch (InterruptedException | ExecutionException e) {
//do some logging
}
}
}
}
Basically this is calling an ExecutorService that manages the thread pool. I call newCachedThreadPool so that it creates new threads as needed instead of just assuming I know how many threads I would need in this case if you do see newFixedThreadPool(n). But, to ensure I get some consistency on thread size, after I loop through the inner loop, I loop through the futures list (a future is a future result of an asynchronous computation) and call f.get which waits if necessary for the computation to complete, and then retrieves its result...
This worked great for what I needed. And the key part is that inside of the overridden run function, the process method takes whatever parameters you want (notice the use of final) instead of trying to force feed run() or worrying about an autowired service when you are calling a constructor. This bypasses all of that.
Thank you to all who put me on the correct path
Related
I'm writing a game engine which performs alhpa-beta search on at a game state, and I'm trying to parallelize it. What I have so far is working at first, and then it seems to slow to a halt. I suspect that this is because I'm not correctly disposing of my threads.
When playing against the computer, the game calls on the getMove() function of a MultiThreadedComputerPlayer object. Here is the code for that method:
public void getMove(){
int n = board.legalMoves.size();
threadList = new ArrayList<WeightedMultiThread>();
moveEvals = new HashMap<Tuple, Integer>();
// Whenever a thread finishes its work at a given depth, it awaits() the other threads
// When all threads are finished, the move evaluations are updated and the threads continue their work.
CyclicBarrier barrier = new CyclicBarrier(n, new Runnable(){
public void run() {
for(WeightedMultiThread t : threadList){
moveEvals.put(t.move, t.eval);
}
}
});
// Prepare and start the threads
for (Tuple move : board.legalMoves) {
MCBoard nextBoard = board.clone();
nextBoard.move(move);
threadList.add(new WeightedMultiThread(nextBoard, weights, barrier));
moveEvals.put(move, 0);
}
for (WeightedMultiThread t : threadList) {t.start();}
// Let the threads run for the maximum amount of time per move
try {
Thread.sleep(timePerMove);
} catch (InterruptedException e) {System.out.println(e);}
for (WeightedMultiThread t : threadList) {
t.stop();
}
// Play the best move
Integer best = infHolder.MIN;
Tuple nextMove = board.legalMoves.get(0);
for (Tuple m : board.legalMoves) {
if (moveEvals.get(m) > best) {
best = moveEvals.get(m);
nextMove = m;
}
}
System.out.println(nextMove + " is the choice of " + name + " given evals:");
for (WeightedMultiThread t : threadList) {
System.out.println(t);
}
board.move(nextMove);
}
And here run() method of the threads in question:
public void run() {
startTime = System.currentTimeMillis();
while(true) {
int nextEval = alphabeta(0, infHolder.MIN, infHolder.MAX);
try{barrier.await();} catch (Exception e) {}
eval = nextEval;
depth += 1;
}
}
I need to be able to interrupt all the threads when time is up-- how am I supposed to implement this? As of now I'm constantly catching (and ignoring) InterruptedExceptions.
Thread.stop was deprecated for a reason. When you interrupt a thread in the middle, the thread doesn't have the chance to properly release resources it was using, and doesn't notify other threads of its completion...something that's very important in multi-threaded apps. I'm not surprised your performance tanks; I would be willing to bet your memory usage shoots through the roof. You also don't recycle the threads, you start and stop them without creating new objects, which means whatever broken state the variables were left in is probably still plaguing them.
A better way is to set a flag that tells the thread it should return. So include in your WeightedMultiThread class a boolean named something like shouldQuit, and set it to false every time start() is called. Then, instead of while (true) do while (!shouldQuit), and instead of t.stop(), use t.shouldQuit = true. After you do that to every thread, have another loop that checks each thread for t.isAlive(), and once every thread has returned, go about your business. You should have much better results that way.
This looks like an ideal place to use an ExecutorService. You can create Callable instances that implement the parallel tasks, submit them to the ExecutorService, then use awaitTermination to enforce a timeout.
For example:
public void getMove() {
ExecutorService service = Executors.newFixedThreadPool(board.legalMoves.size());
List<Future<Something>> futures = new ArrayList<Future<Something>>(board.legalMoves.size());
for (Tuple move : board.legalMoves) {
futures.add(service.submit(new WeightedMultiThread(...)));
}
service.awaitTermination(timePerMove, TimeUnit.MILLISECONDS);
service.shutdownNow(); // Terminate all still-running jobs
for (Future<Something> future : futures) {
if (future.isDone()) {
Something something = future.get();
// Add best move logic here
}
}
...
}
Replace Something with something that encapsulates information about the move that has been evaluated. I'd suggest Something be a class that holds the Tuple and its associated score. Your WeightedMultiThread class can do something like this:
class WeightedMultiThread implements Callable<Something> {
public Something call() {
// Compute score
...
// Return an appropriate data structure
return new Something(tuple, score);
}
}
Even better would be to create the ExecutorService once and re-use it for each call to getMove. Creating threads is expensive, so best to only do it once if you can. If you take this approach then you should not call shutdownNow, but instead use the Future.cancel method to terminate jobs that have not completed in time. Make sure your WeightedMultiThread implementation checks for thread interruption and throws an InterruptedException. That's usually a good way to write a long-running task that needs to be interruptible.
EDIT:
Since you're doing a level-by-level exploration of the game space, I'd suggest that you encode that in the getMove function rather than in the Tuple evaluation code, e.g.
public Tuple getMove() {
ExecutorService service = ...
Tuple best = null;
long timeRemaining = MAX_TIME;
for (int depth = 0; depth < MAX_DEPTH && timeRemaining > 0; ++depth) {
long start = System.currentTimeMillis();
best = evaluateMoves(depth, service, timeRemaining);
long end = System.currentTimeMillis();
timeRemaining -= (end - start);
}
return best;
}
private Tuple evaluateMoves(int depth, ExecutorService service, long timeRemaining) {
List<Future<Whatever>> futures = service.submit(...); // Create all jobs at this depth
service.awaitTermination(timeRemaining, TimeUnit.MILLISECONDS);
// Find best move
...
return best;
}
That could probably be cleaner, but you get the idea.
The most sensitive way is to use interruption mechanism. Thread.interrupt() and Thread.isInterrupted() methods. This ensures your message will be delivered to a thread even if it sits inside a blocking call (remember some methods declare throwing InterruptedException?)
P.S. It would be useful to read Brian Goetz's "Java Concurrency in Practice" Chapter 7: Cancellation and Shutdown.
I am developing a program that can send http requests to fetch documents.
I have fill a queue with all the requests items:
Queue<RequestItem> requestItems = buildRequest4Docs();
Then,
int threadNum = requestItems.size();
//ExecutorService exs = Executors.newFixedThreadPool(threadNum);
for (int i = 0; i < threadNum; i++) {
ResponseInterface response = new CMSGOResponse();
RequestTask task = new RequestTask(requestItems.poll(), this, response);
task.run();
//exs.execute(new RequestTask(requestItems.poll(), this, response));
}
//exs.shutdown();
I am confused here, in the for loop,does the tasks run simultaneously? Or the tasks run one by one?
Thanks!
In the way you got it now the tasks will be executed one by one. If you uncomment the code you got now as comments and comment the lines RequestTask task = new RequestTask(requestItems.poll(), this, response); and task.run(); you will get a concurrent execution.
So for the concurrent execution it has to look like this:
int threadNum = requestItems.size();
ExecutorService exs = Executors.newFixedThreadPool(threadNum);
for (int i = 0; i < threadNum; i++) {
ResponseInterface response = new CMSGOResponse();
exs.execute(new RequestTask(requestItems.poll(), this, response));
}
exs.shutdown();
while (! exs.isTerminated()) {
try {
exs.awaitTermination(1L, TimeUnit.DAYS);
}
catch (InterruptedException e) {
// you may or may not care here, but if you truly want to
// wait for the pool to shutdown, just ignore the exception
// otherwise you'll have to deal with the exception and
// make a decision to drop out of the loop or something else.
}
}
In addition to that I suggest, that you do not bind the amount of threads created with the ExecutorService to the amount of task you got to work. Connecting it to the amount of processors of the host system is usually a better method. To get the amount of processors use: Runtime.getRuntime().availableProcessors()
And in the executor service initialized like this you put the items of your queue. But that works nicely without fetching the total size, rather by polling the Queue until it does not return additional data.
The final result of my proposals could look like this:
final int threadNum = Runtime.getRuntime().availableProcessors();
final ExecutorService exs = Executors.newFixedThreadPool(threadNum);
while (true) {
final RequestItem requestItem = requestItems.poll();
if (requestItem == null) {
break;
}
final ResponseInterface response = new CMSGOResponse();
exs.execute(new RequestTask(requestItem , this, response));
}
exs.shutdown();
I am confused here, in the for loop,does the tasks run simultaneously? Or the tasks run one by one?
With the code you've posted, they'll run one-by-one, because (assuming RequestTask is a subclass of Thread) you've called run. You should call start. Now that you've said RequestTask implements Runnable, the correct code wouldn't call start (it doesn't have one!) but rather new Thread(task);. (But it looks like you've now received a good answer regarding the ExecutorService, which is another way to do it.)
Assuming you call start start them on different threads instead, then yes, they'll all run in parallel (as much as they can on the hardware, etc.).
Currently you are running your thread sequentially, Well you have two ways to run threads.(Assuming that RequestTask extends Thread)
I.Either create thread object and call start() method.
RequestTask task = new RequestTask(requestItems.poll(), this, response);
task.start(); // run() method will be called, you don't need to call it
II.Or create ExecutorService
ExecutorService pool = Executors.newFixedThreadPool(poolSize);
//....
for (int i = 0; i < threadNum; i++) {
ResponseInterface response = new CMSGOResponse();
RequestTask task = new RequestTask(requestItems.poll(), this, response);
pool.execute(task);
}
You are running them one by one in the current thread. You need to use the ExecutorService to run them concurrently.
I am confused here, in the for loop,does the tasks run simultaneously? Or the tasks run one by one?
Task will be executed in the same thread i.e. one by one since you are calling run() rather that start , it will not run the task in new thread .
int threadNum = requestItems.size();
ExecutorService exs = Executors.newFixedThreadPool(threadNum);
ResponseInterface response = new CMSGOResponse();
RequestTask task = new RequestTask(requestItems.poll(), this, response);
exs.execute(task );
exs.shutdown();
In above case task will be executed in new thread and as soon as you assign 10 different task to ExecutorService they will be executed asynchronously in different threads.
I usually tend to create my Threads (or classes implementing Interface), THEN launch them with the start() method.
In your case, since RequestTask implements Runnable, you could add a start() method like this :
public class RequestTask implements Runnable {
Thread t;
boolean running;
public RequestTask() {
t = new Thread(this);
}
public void start() {
running = true; // you could use a setter
t.start();
}
public void run() {
while (running) {
// your code goes here
}
}
}
, then :
int threadNum = requestItems.size();
RequestTask[] rta = new RequestTask[threadNum];
// Create the so-called Threads ...
for (int i=0;i<threadNum;i++) {
rta[i] = new RequestTask(requestItems.poll(), this, new CMSGOResponse());
}
// ... THEN launch them
for (int i=0;i<threadNum;i++) {
rta[i].start();
}
I'm new to concurrent programing and have been working on code which has a queue of items to be processed, this is passed to some worker threads, the number specified by the user. At the moment I've just tried to do it with two worker threads plus the main.
private static class workerThread extends Thread {
workerThread(){
super();
}
public void run(){
while (!workQueue.isEmpty()) {
String x = workQueue.remove();
//System.out.println("work queue size: " + workQueue.size());
Vector<String> list2 = new Vector<String>((Vector) table.get(x));
list2 = process(x, list2);
//System.out.println(list2 + "list2");
table.put(x, list2);
//System.out.println(x + "key" + "value" + vvv);
}
}
That's the thread workerthread class, I've tried to call it just by creating two new threads:
workerThread wt = new workerThread();
workerThread wt2 = new workerThread();
wt.start();
wt2.start();
try {
wt.join();
wt2.join();
} catch (InterruptedException ex) {
Logger.getLogger(includeCrawler.class.getName()).log(Level.SEVERE, null, ex);
}
I'm not sure if this is right, or will have any benfit due to waiting for the joins? Thanks for any help.
A much cleaner and scalable way to do this is to use a thread pool created by the Executors class.
By the way, the Vector class is obsolete and should not be used anymore - use ArrayList instead and dump whatever book or tutorial where you learned to use Vector - it's more than a decade out of date.
Just a few references, I think you want to use a BlockingQueue along with an ExecutorService and a Runnable or Callable.
final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); perhaps even an instance variable (private static final ExecutorService POOL = ...). For an I/O bound application you might want to use more threads than the available processors. Then again you don't want to use Vector. Use another List implementation (usually ArrayList is the one to use).
BTW: If you want to master concurrent programming you might also want to read about Akka and Actors/STM instead of using the usual shared mutability model.
Edit: I would definately recommend http://pragprog.com/book/vspcon/programming-concurrency-on-the-jvm and Effective Java from Josh(ua) Bloch.
You definitely have to use Executors. This is an example just for reference. It works on a single thread, but I think it's a good start for you. It's easily adaptable to an arbitrary number of threads.
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<MyObject> f =
executor.submit(new Callable<MyObject>() {
#Override
public MyObject call() throws Exception {
MyObject obj = new MyObject();
// do stuff
return obj;
}
});
MyObject myObject =
new MyObject();
try {
myObject = f.get(500, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e) {
// stuff
}
catch (ExecutionException e) {
// stuff
}
catch (TimeoutException e) {
// stuff
}
finally {
executor.shutdown();
}
In this case I wanted to wait at most 500ms before timeout, but this is optional.
Hope this could help.
The setup:
I am in the process of changing the way a program works under the hood. In the current version works like this:
public void threadWork( List<MyCallable> workQueue )
{
ExecutorService pool = Executors.newFixedThreadPool(someConst);
List<Future<myOutput>> returnValues = new ArrayList<Future<myOutput>>();
List<myOutput> finishedStuff = new ArrayList<myOutput>();
for( int i = 0; i < workQueue.size(); i++ )
{
returnValues.add( pool.submit( workQueue.get(i) ) );
}
while( !returnValues.isEmpty() )
{
try
{
// Future.get() waits for a value from the callable
finishedStuff.add( returnValues.remove(0).get(0) );
}
catch(Throwable iknowthisisbaditisjustanexample){}
}
doLotsOfThings(finsihedStuff);
}
But the new system is going to use a private inner Runnable to call a synchronized method that writes the data into a global variable. My basic setup is:
public void threadReports( List<String> workQueue )
{
ExecutorService pool = Executors.newFixedThreadPool(someConst);
List<MyRunnable> runnables = new ArrayList<MyRunnable>()
for ( int i = 0; i < modules.size(); i++ )
{
runnables.add( new MyRunnable( workQueue.get(i) );
pool.submit(threads.get(i));
}
while( !runnables.isEmpty() )
{
try
{
runnables.remove(0).wait(); // I realized that this wouldn't work
}
catch(Throwable iknowthisisbaditisjustanexample){}
}
doLotsOfThings(finsihedStuff); // finishedStuff is the global the Runnables write to
}
If you read my comment in the try of the second piece of code you will notice that I don't know how to use wait(). I had thought it was basically like thread.join() but after reading the documentation I see it is not.
I'm okay with changing some structure as needed, but the basic system of taking work, using runnables, having the runnables write to a global variable, and using a threadpool are requirements.
The Question
How can I wait for the threadpool to be completely finished before I doLotsOfThings()?
You should call ExecutorService.shutdown() and then ExecutorService.awaitTermination.
...
pool.shutdown();
if (pool.awaitTermination(<long>,<TimeUnit>)) {
// finished before timeout
doLotsOfThings(finsihedStuff);
} else {
// Timeout occured.
}
Try this:
pool.shutdown();
pool.awaitTermination(WHATEVER_TIMEOUT, TimeUnit.SECONDS);
Have you considered using the Fork/Join framework that is now included in Java 7. If you do not want to use Java 7 yet you can get the jar for it here.
public void threadReports( List<String> workQueue )
{
ExecutorService pool = Executors.newFixedThreadPool(someConst);
Set<Future<?>> futures = new HashSet<Future<?>>();
for ( int i = 0; i < modules.size(); i++ )
{
futures.add(pool.submit(threads.get(i)));
}
while( !futures.isEmpty() )
{
Set<Future<?>> removed = new Set<Future<?>>();
for(Future<?> f : futures) {
f.get(100, TimeUnit.MILLISECONDS);
if(f.isDone()) removed.add(f);
}
for(Future<?> f : removed) futures.remove(f);
}
doLotsOfThings(finsihedStuff); // finishedStuff is the global the Runnables write to
}
shutdownis a lifecycle method of the ExecutorService and renders the executor unusable after the call. Creating and destroying ThreadPools in a method is as bad as creating/destroying threads: it pretty much defeats the purpose of using threadpool, which is to reduce the overhead of thread creation by enabling transparent reuse.
If possible, you should maintain your ExecutorService lifecycle in sync with your application. - create when first needed, shutdown when your app is closing down.
To achieve your goal of executing a bunch of tasks and waiting for them, the ExecutorService provides the method invokeAll(Collection<? extends Callable<T>> tasks) (and the version with timeout if you want to wait a specific period of time.)
Using this method and some of the points mentioned above, the code in question becomes:
public void threadReports( List<String> workQueue ) {
List<MyRunnable> runnables = new ArrayList<MyRunnable>(workQueue.size());
for (String work:workQueue) {
runnables.add(new MyRunnable(work));
}
// Executor is obtained from some applicationContext that takes care of lifecycle mgnt
// invokeAll(...) will block and return when all callables are executed
List<Future<MyRunnable>> results = applicationContext.getExecutor().invokeAll(runnables);
// I wouldn't use a global variable unless you have a VERY GOOD reason for that.
// b/c all the threads of the pool doing work will be contending for the lock on that variable.
// doLotsOfThings(finishedStuff);
// Note that the List of Futures holds the individual results of each execution.
// That said, the preferred way to harvest your results would be:
doLotsOfThings(results);
}
PS: Not sure why threadReports is void. It could/should return the calculation of doLotsOfThings to achieve a more functional design.
I am using the ThreadPoolExecutor to implement threading in my Java Application.
I have a XML which I need to parse and add each node of it to a thread to execute the completion. My implementation is like this:
parse_tp is a threadpool object created & ParseQuotesXML is the class with the run method.
try {
List children = root.getChildren();
Iterator iter = children.iterator();
//Parsing the XML
while(iter.hasNext()) {
Element child = (Element) iter.next();
ParseQuotesXML quote = new ParseQuotesXML(child, this);
parse_tp.execute(quote);
}
System.out.println("Print it after all the threads have completed");
catch(Exception ex) {
ex.printStackTrace();
}
finally {
System.out.println("Print it in the end.");
if(!parse_tp.isShutdown()) {
if(parse_tp.getActiveCount() == 0 && parse_tp.getQueue().size() == 0 ) {
parse_tp.shutdown();
} else {
try {
parse_tp.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
log.info("Exception while terminating the threadpool "+ex.getMessage());
ex.printStackTrace();
}
}
}
parse_tp.shutdown();
}
The problem is, the two print out statements are printed before the other threads exit. I want to make the main thread wait for all other threads to complete.
In normal Thread implementation I can do it using join() function but not getting a way to achieve the same in ThreadPool Executor. Also would like to ask if the code written in finally block to close the threadpool proper ?
Thanks,
Amit
A CountDownLatch is designed for this very purpose. Examples may be found here and here. When the number of threads is not known in advance, consider a Phaser, new in Java 1.7, or an UpDownLatch.
To answer your second question, I think you are doing a reasonable job trying to clean up your thread pool.
With respect to your first question, I think the method that you want to use is submit rather than execute. Rather than try to explain it all in text, here's an edited fragment from a unit test that I wrote that makes many tasks, has each of them do a fragment of the total work and then meets back at the starting point to add the results:
final AtomicInteger messagesReceived = new AtomicInteger(0);
// ThreadedListenerAdapter is the class that I'm testing
// It's not germane to the question other than as a target for a thread pool.
final ThreadedListenerAdapter<Integer> adapter =
new ThreadedListenerAdapter<Integer>(listener);
int taskCount = 10;
List<FutureTask<Integer>> taskList = new ArrayList<FutureTask<Integer>>();
for (int whichTask = 0; whichTask < taskCount; whichTask++) {
FutureTask<Integer> futureTask =
new FutureTask<Integer>(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
// Does useful work that affects messagesSent
return messagesSent;
}
});
taskList.add(futureTask);
}
for (FutureTask<Integer> task : taskList) {
LocalExecutorService.getExecutorService().submit(task);
}
for (FutureTask<Integer> task : taskList) {
int result = 0;
try {
result = task.get();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
} catch (ExecutionException ex) {
throw new RuntimeException("ExecutionException in task " + task, ex);
}
assertEquals(maxMessages, result);
}
int messagesSent = taskCount * maxMessages;
assertEquals(messagesSent, messagesReceived.intValue());
I think this fragment is similar to what you're trying to do. The key components were the submit and get methods.
First of all you can use ThreadPoolExecutor.submit() method, which returns Future instance, then after you submitted all your work items you can iterate trough those futures and call Future.get() on each of them.
Alternatively, you can prepare your runnable work items and submit them all at once using ThreadPoolExecutor.invokeAll(), which will wait until all work items completed and then you can get the execution results or exception calling the same Future.get() method.