Java Future : How to unblock Main thread while executing Aysnc call - java

When I do async call using ExecutorService, it returns Future Object. Based on the boolean value it returns, I have to log the status of the async call.
But when I try to call the method get method from the future object, it blocks the main thread execution.
Is it possible to unblock the main thread execution?
public class FutureExample {
static HystrixCommand<Boolean> hystrixCommand;
public FutureExample(HystrixCommand<Boolean> hystrixCommand){
FutureExample.hystrixCommand = hystrixCommand;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
Boolean something = asyncCall();
if(something) {
System.out.println("Future task is done");
}
System.out.println("Don't wait for async call");
}
private static Boolean asyncCall() throws InterruptedException, ExecutionException {
Future<Boolean> response = hystrixCommand.queue(); // Aysnc Call to remote server
return response.get(); //this is blocking main thread
}
}

The good thing about futures is to be able to release threads until the answer arrives.
So I recommend you to use a Future implementation, like CompletableFuture:
final ExecutorService executorService = Executors.newFixedThreadPool(10);
CompletableFuture.supplyAsync(() -> {
try {
return hystrixCommand.queue();
} catch (Exception e) {
return false;
}
}, executorService);
This will work on another thread and when that future is over it will be done.

According to JavaDocs, get() method waits if necessary for the computation to complete, and then retrieves its result.
If you want to get the result once the task is completed, use isDone() function, which returns true if the task completed (normally, exceptionally, etc.). And invoke get() afterwards.
Also, you can use get(long timeout, TimeUnit unit) function to wait only for the given period of time. In this case the main thread will be "unblocked" automatically if either the time is out or the task has completed.

If you need to execute code in the main thread while the async task is running, you will need to redesign your asyncCall method to make it return a future instead.
An example:
private static Future<Boolean> asyncCall()
throws InterruptedException, ExecutionException {
return hystrixCommand.queue();
}
This way, the main method makes the call regarding when to block/wait:
public static void main(String[] args)
throws InterruptedException, ExecutionException {
Future<Boolean> something = asyncCall();
//do something while async call is running
//to check whether it's done running:
if(something.isDone()) {
System.out.println("Future task is done");
}
//when you're finally ready to wait:
System.out.println("Waiting for async call to finish");
Boolean result = something.get();
}

Related

What's the advantage of using ExecutorService with immediate get()?

I see in the code here a lot of
executorService.submit(() -> {
// do stuff
}).get();
...and I wonder why is the executorService used like this, submitting something you will immediately get?
Calling an immediate get() forces the ExecutorService to process "do stuff" in the executor service's threadpool rather than the local thread, which may for example choke processing if the maximum number of threads allocated to it is small, despite there being a great many threads running to handle requests.
Consider an obvious example of an executor service that has only 1 thread:
ExecutorService executorService = Executors.newSingleThreadExecutor();
and the example code being called from say an HttpRequestHandler.
By using the immediate get() processing of "do stuff" will be serialized, which may be desirable or a requirement, despite there being many simultaneous requests being processed each in their own thread.
Without the wrapper of executorService.submit(...).get(), processing of "do stuff" would be done in parallel in the request handler's thread, which may be fine or may cause problems if "do stuff" is particularly expensive or constrained in some way if parallelism is unbounded.
Parallelism can be limited/bounded instead of eliminated as follows:
ExecutorService executorService = Executors.newFixedThreadPool(3);
would limit processing to (for example) a maximum of 3 concurrently processing "do stuff"s, despite there being a great many requests being processed simultaneously.
Other more subtle effects are possible to via the choice of Thread in which "do stuff" runs. Consider:
ExecutorService executorService = Executors.newSingleThreadExecutor(myThreadFactory);
will make "do stuff" run in a custom type of thread, rather than in the thread type chosen for the HttpRequestHandler.
submitting something you will immediately get
Just because you submit the task and 'get' it immediately, that doesn't necessarily mean it will be run immediately by the ExecutorService.
Here's a practical example of how this is useful:
You have a web server, which returns weather data. When an HTTP request comes in, you need to make a connection to a weather API to retrieve the weather data.
However, that weather API only allows two concurrent connections.
One way to solve this problem would be to have an ExecutorService with only two available threads.
Now, no matter how many servlet threads simultaneously submit tasks for execution, you can ensure that only two threads at a time can perform requests against the weather API. The servlet threads will block until the weather API is available to provide the servlet with the requested data.
Because somebody blindly copied this from Javadoc, which reads "If you would like to immediately block waiting for a task, you can use constructions of the form result = exec.submit(aCallable).get();"
Apart from that and the slight difference in exception semantics that #Michael mentioned in his comment on the question, there is also a slight difference wrt. interrupting of threads: if // do stuff blocks uninterruptedly you would still be able to interrupt the blocking call to Future.get or cancel the future. Note though, this doesn't do anything to the thread running // do stuff. That thread would keep blocking, only your main thread becomes unblocked.
The only use case that I can think of is when:
code that calls it MUST return some result synchronously (i.e. it's implementing some sync api handling http request or whatnot)
the executor that is called is a ForkJoinPool and the task submitted is the RecursiveTask that will internally fork. This way you could use more than one cpu to execute whole task.
Using a .get() call on a Future allows one to abstract the details of how exactly one delivers the result. Excusing the length of the example, if one looks at the .get() method for the below class, one can see that to implement the same sort of timing mechanism in the calling thread would be an excessive amount of boilerplate code. By abstracting it, the calling thread will simply block indefinitely while the worker thread worries about the details of delivering on the promise of its Future
import java.util.Optional;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
class DecayingRetry<T> implements Future<T> {
protected final ScheduledExecutorService executor;
protected final Callable<T> callable;
private final boolean isOwnExecutor;
protected ScheduledFuture<?> future;
#SuppressWarnings("OptionalUsedAsFieldOrParameterType")
protected Optional<?> result;
protected boolean isDone;
protected boolean isCancelled;
protected final ReentrantLock lock;
private final double maxDelay;
private double initialDelay;
private final TimeUnit timeUnit;
private DecayingRetry(ScheduledExecutorService executor,
boolean isOwnExecutor,
Callable<T> callable,
long initialDelay,
long maxDelay,
TimeUnit timeUnit) {
this.isOwnExecutor = isOwnExecutor;
lock = new ReentrantLock(true);
lock.lock();
this.executor = executor;
this.callable = callable;
isCancelled = false;
isDone = false;
if (maxDelay < 0) {
this.maxDelay = Double.POSITIVE_INFINITY;
} else {
this.maxDelay = maxDelay;
}
lock.lock();
this.initialDelay = (double) initialDelay;
this.timeUnit = timeUnit;
future = executor.schedule(this::delayLoop, initialDelay, timeUnit);
}
public static <T> T on(Callable<T> callable, long initialDelay, long maxDelay, TimeUnit timeUnit) throws Exception {
try {
return Optional.ofNullable(callable.call()).orElseThrow(IllegalStateException::new);
} catch (IllegalStateException ignored) {
try {
return new DecayingRetry<>(Executors.newSingleThreadScheduledExecutor(),
true,
callable,
initialDelay,
maxDelay,
timeUnit).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
System.exit(-1);
}
}
return null;
}
public static <T> T on(Callable<T> callable,
ScheduledExecutorService executor,
long initialDelay,
long maxDelay,
TimeUnit timeUnit) throws Exception {
try {
return Optional.ofNullable(callable.call()).orElseThrow(IllegalStateException::new);
} catch (IllegalStateException ignored) {
try {
return new DecayingRetry<>(executor,
false,
callable,
initialDelay,
maxDelay,
timeUnit).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
System.exit(-1);
}
}
return null;
}
synchronized private void delayLoop() {
if (isDone) {
return;
}
try {
result = Optional.ofNullable(callable.call());
} catch (Exception e) {
result = Optional.of(e);
isDone = true;
return;
}
if (!result.isPresent()) {
if (initialDelay < maxDelay) {
initialDelay *= 1.618033988749; //PHI
initialDelay = Math.min(maxDelay, initialDelay);
}
future = executor.schedule(this::delayLoop, (long) initialDelay, timeUnit);
} else {
isDone = true;
lock.unlock();
}
}
public boolean cancel(boolean mayInterruptIfRunning) {
if (isDone) {
return false;
} else if (future.cancel(mayInterruptIfRunning)) {
isCancelled = true;
isDone = true;
return true;
}
return false;
}
#Override
public boolean isCancelled() {
return isCancelled;
}
#Override
public boolean isDone() {
return isDone;
}
#Override
#NotNull
public T get() throws InterruptedException, ExecutionException {
lock.lock();
while (!isDone) { // lock acquired too early for some reason, so we allow the worker thread to grab it
lock.unlock();
lock.lock();
}
if (result.isPresent()) {
if (result.get() instanceof Throwable) {
throw new ExecutionException((Throwable) result.get());
}
if (isOwnExecutor) {
executor.shutdown();
}
//noinspection unchecked
return (T) result.get();
}
throw new ExecutionException(new IllegalStateException("Retry result was null"));
}
public T get(long timeout, #NotNull TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
throw new ExecutionException(new IllegalStateException("Not implemented"));
}
}

Using both timeout and semaphore for Thread blocking

I have a method to run that makes connection to server, and when server fails, would wait until it receives a message that server is up again. However, this entire method should have a timeout, and if it is over the time, method should interrupt and return error log instead.
private Semaphore sem = new Semaphore(0);
private TimeUnit unit = TimeUnit.MILLISECONDS;
public String some_method(Object params, long timeout, TimeUnit unit) {
long time = 0;
while(time < timeout) { // not sure about timeout method
try {
//some task that is prone to ServerConnectException
return; // returns value and exits
} catch(ServerConnectException ex) {
sem.acquire();
} catch(InterruptedException uhoh) {
System.out.println("uhoh, thread interrupted");
}
// increment time somehow
}
sem.release();
return null; // a message of task incompletion
}
I was thinking about running a thread containing semaphore that blocks thread if there's a server failure problem, but I cannot seem to organize thread such that it will contain the semaphore but be contained by method itself.
QUESTION:
- However, the method is already in a gigantic class and making separate Thread for just that method will mess up entire call hierarchy as well as whole API, so I don't want to do that. I need some process that runs along with the some_method and places lock and release on its processes as needed, with timeout. What should I be thinking? Some other concurrency wrapper like executor?
Thanks!
Semaphore doesn't seem to be the right concurrency primitive to use here, as you don't really need a utility for locking, but rather a utility to help you coordinate inter-thread communication.
If you need to communicate a stream of values, you would typically use a blocking queue, but if you need to communicate a single value, a CountDownLatch and a variable do the trick. For example (untested):
public String requestWithRetry(final Object params, long timeout, TimeUnit unit) throws InterruptedException {
String[] result = new String[1];
CountDownLatch latch = new CountDownLatch(1);
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
result[0] = request(params);
latch.countDown();
return;
}
catch(OtherException oe) {
// ignore and retry
}
catch(InterruptedException ie) {
// task was cancelled; terminate thread
return;
}
}
}
});
t.start();
try {
if (!latch.await(timeout, unit)) {
t.interrupt(); // cancel the background task if timed out
}
// note that this returns null if timed out
return result[0];
}
catch(InterruptedException ie) {
t.interrupt(); // cancel the background task
throw ie;
}
}
private String request(Object params) throws OtherException, InterruptedException {
// should handle interruption to cancel this operation
return null;
}

What is the difference between ExecutorService.submit and ExecutorService.execute in this code in Java?

I am learning to use ExectorService to pool threads and send out tasks. I have a simple program below
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
class Processor implements Runnable {
private int id;
public Processor(int id) {
this.id = id;
}
public void run() {
System.out.println("Starting: " + id);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("sorry, being interupted, good bye!");
System.out.println("Interrupted " + Thread.currentThread().getName());
e.printStackTrace();
}
System.out.println("Completed: " + id);
}
}
public class ExecutorExample {
public static void main(String[] args) {
Boolean isCompleted = false;
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 5; i++) {
executor.execute(new Processor(i));
}
//executor does not accept any more tasks but the submitted tasks continue
executor.shutdown();
System.out.println("All tasks submitted.");
try {
//wait for the exectutor to terminate normally, which will return true
//if timeout happens, returns false, but this does NOT interrupt the threads
isCompleted = executor.awaitTermination(100, TimeUnit.SECONDS);
//this will interrupt thread it manages. catch the interrupted exception in the threads
//If not, threads will run forever and executor will never be able to shutdown.
executor.shutdownNow();
} catch (InterruptedException e) {
}
if (isCompleted) {
System.out.println("All tasks completed.");
} else {
System.out.println("Timeout " + Thread.currentThread().getName());
}
}
}
It does nothing fancy, but creates two threads and submits 5 tasks in total. After each thread completes its task, it takes the next one,
In the code above, I use executor.submit. I also changed to executor.execute. But I do not see any difference in the output. In what way are the submit and execute methods different?
This what the API says
Method submit extends base method Executor.execute(java.lang.Runnable) by creating and returning a Future that can be used to cancel execution and/or wait for completion. Methods invokeAny and invokeAll perform the most commonly useful forms of bulk execution, executing a collection of tasks and then waiting for at least one, or all, to complete. (Class ExecutorCompletionService can be used to write customized variants of these methods.)
But it's not clear to me as what it exactly means?
As you see from the JavaDoc execute(Runnable) does not return anything.
However, submit(Callable<T>) returns a Future object which allows a way for you to programatically cancel the running thread later as well as get the T that is returned when the Callable completes. See JavaDoc of Future for more details
Future<?> future = executor.submit(longRunningJob);
...
//long running job is taking too long
future.cancel(true);
Moreover,
if future.get() == null and doesn't throw any exception then Runnable executed successfully
The difference is that execute simply starts the task without any further ado, whereas submit returns a Future object to manage the task. You can do the following things with the Future object:
Cancel the task prematurely, with the cancel method.
Wait for the task to finish executing, with get.
The Future interface is more useful if you submit a Callable to the pool. The return value of the call method will be returned when you call Future.get. If you don't maintain a reference to the Future, there is no difference.
execute: Use it for fire and forget calls
submit: Use it to inspect the result of method call and take appropriate action on Future objected returned by the call
Major difference: Exception handling
submit() hides un-handled Exception in framework itself.
execute() throws un-handled Exception.
Solution for handling Exceptions with submit()
Wrap your Callable or Runnable code in try{} catch{} block
OR
Keep future.get() call in try{} catch{} block
OR
implement your own ThreadPoolExecutor and override afterExecute method
Regarding tour other queries on
invokeAll:
Executes the given tasks, returning a list of Futures holding their status and results when all complete or the timeout expires, whichever happens first.
invokeAny:
Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do before the given timeout elapses.
Use invokeAll if you want to wait for all submitted tasks to complete.
Use invokeAny if you are looking for successful completion of one task out of N submitted tasks. In this case, tasks in progress will be cancelled if one of the tasks completes successfully.
Related post with code example:
Choose between ExecutorService's submit and ExecutorService's execute
A main difference between the submit() and execute() method is that ExecuterService.submit()can return result of computation because it has a return type of Future, but execute() method cannot return anything because it's return type is void. The core interface in Java 1.5's Executor framework is the Executor interface which defines the execute(Runnable task) method, whose primary purpose is to separate the task from its execution.
Any task submitted to Executor can be executed by the same thread, a worker thread from a thread pool or any other thread.
On the other hand, submit() method is defined in the ExecutorService interface which is a sub-interface of Executor and adds the functionality of terminating the thread pool, along with adding submit() method which can accept a Callable task and return a result of computation.
Similarities between the execute() and submit() as well:
Both submit() and execute() methods are used to submit a task to Executor framework for asynchronous execution.
Both submit() and execute() can accept a Runnable task.
You can access submit() and execute() from the ExecutorService interface because it also extends the Executor interface which declares the execute() method.
Apart from the fact that submit() method can return output and execute() cannot, following are other notable differences between these two key methods of Executor framework of Java 5.
The submit() can accept both Runnable and Callable task but execute() can only accept the Runnable task.
The submit() method is declared in ExecutorService interface while execute() method is declared in the Executor interface.
The return type of submit() method is a Future object but return type of execute() method is void.
If you check the source code, you will see that submit is sort of a wrapper on execute
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
Submit - Returns Future object, which can be used to check result of submitted task. Can be used to cancel or to check isDone etc.
Execute - doesn't return anything.
The execute(Runnable command) is the implemented method from Interface Executor. It means just execute the command and gets nothing returned.
ExecutorService has its own methods for starting tasks: submit, invokeAny and invokeAll all of which have Callable instances as their main targets. Though there're methods having Runnable as input, actulaly Runnable will be adapted to Callable in the method. why Callable? Because we can get a Future<T> result after the task is submitted.
But when you transform a Runnable to a Callable, result you get is just the value you pass:
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}
So, what's the point that we pass a Runnable to submit instead of just getting the result when the task is finished? Because there's a method which has only Runnable as parameter without a particular result.
Read the javadoc of Future:
If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.
So, if you just want to execute a Runnable task without any value returned, you can use execute().
if you want to run a Callable task, or
if you want to run a Runnable task with a specified result as the completion symbol, or
if you want to run a task and have the ability to cancel it,
you should use submit().
On top of previous responses, i.e.
execute(..) runs the task and forget about it
submit(...) returns a future;
The main advantage with the future is that you can establish a timeout. This might come very handy if you have an executor with a limited number of threads and your executions are taking forever, it will not hang the process.
Example 1: hangs forever and fills the executor
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i=0; i < 5; i++) {
executor.execute(() -> {
while (true) {
System.out.println("Running...")
Thread.sleep(Long.MAX_VALUE)
}
});
}
Your output will be (i.e. only 2 and it gets stuck):
Running...
Running...
On the other hand, you can use submit and add a timeout:
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i=0; i < 5; i++) {
Future future = executor.submit(() -> {
while (true) {
System.out.println("Running...");
Thread.sleep(Long.MAX_VALUE);
}
});
try {
future.get(1, TimeUnit.SECONDS);
} catch (Exception e) {
if (!future.isDone()) {
System.out.println("Oops: " + e.getClass().getSimpleName());
future.cancel(true);
}
}
}
The output will look like this (notice that the executor does not get stuck, but you need to manually cancel the future):
Running...
Oops: TimeoutException
Running...
Oops: TimeoutException
Running...
Oops: TimeoutException
Running...
Oops: TimeoutException
Running...
Oops: TimeoutException
basically both calls execute,if u want future object you shall call submit() method
here from the doc
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
as you can see java really has no way to start a thread other than calling run() method, IMO. since i also found that Callable.call() method is called inside run() method. hence if the object is callable it would still call run() method, which inturn would call call() method
from doc.
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}

setting interrupt bit does not make Future.get() throw TimeoutException

Why doesn't setting the interrupt bit in a Callable cause the Future that represents the Callable to throw a TimeoutException when Future.get() is called?
public class ExecutorServiceTest extends MockitoTestCase {
private static CountDownLatch latch1 = new CountDownLatch(1);
class TaskChecksForInterruptedExcAndDoesSetInterruptedBit implements Callable<String> {
#Override
public String call() {
latch1.countDown();
while (!Thread.currentThread().isInterrupted()) {
}
Thread.currentThread().interrupt();
return "blah";
}
}
void testInterrupt() throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(numThreads);
Future<String> future = pool.submit(new TaskChecksForInterruptedExcAndDoesSetInterruptedBit());
latch1.await(); // Don't interrupt the Callable until it actually starts processing
pool.shutdownNow();
try {
future.get(100, TimeUnit.MILLISECONDS);
} catch (final TimeoutException e) {
// Why doesn't this get called!
return;
}
fail();
}
}
the shutdownNow() call attempts to interrupt all running tasks. In this case the interruption is detected in your busy loop, so the code continues and the Callable returns "blah" (and not an exception)
TimeoutException, according to the spec, is thrown only if the thread waits for the complete timeout period, but no result becomes available. Interruption doesn't fit into this scenario.
Your usage of CountDownLatch is incorrect. You decrement it, but I see no call to latch1.await()

Sync version of async method

What's the best way to make a synchronous version of an asynchronous method in Java?
Say you have a class with these two methods:
asyncDoSomething(); // Starts an asynchronous task
onFinishDoSomething(); // Called when the task is finished
How would you implement a synchronous doSomething() that does not return until the task is finished?
Have a look at CountDownLatch. You can emulate the desired synchronous behaviour with something like this:
private CountDownLatch doneSignal = new CountDownLatch(1);
void main() throws InterruptedException{
asyncDoSomething();
//wait until doneSignal.countDown() is called
doneSignal.await();
}
void onFinishDoSomething(){
//do something ...
//then signal the end of work
doneSignal.countDown();
}
You can also achieve the same behaviour using CyclicBarrier with 2 parties like this:
private CyclicBarrier barrier = new CyclicBarrier(2);
void main() throws InterruptedException{
asyncDoSomething();
//wait until other party calls barrier.await()
barrier.await();
}
void onFinishDoSomething() throws InterruptedException{
//do something ...
//then signal the end of work
barrier.await();
}
If you have control over the source-code of asyncDoSomething() I would, however, recommend redesigning it to return a Future<Void> object instead. By doing this you could easily switch between asynchronous/synchronous behaviour when needed like this:
void asynchronousMain(){
asyncDoSomethig(); //ignore the return result
}
void synchronousMain() throws Exception{
Future<Void> f = asyncDoSomething();
//wait synchronously for result
f.get();
}

Categories

Resources