Access Callable after CancellationException exception of FutureTask.get - java

What's the prefered method to access the underlying Callable after a CancellationException exception of a FutureTask.get?
I have the following code -
public class Ping implements Callable
{
public Ping(String serverName)
{
// stuff
}
// call() method, etc.
}
// other code
futures = executor.invokeAll(callables, TIMEOUT_SECONDS, TimeUnit.SECONDS);
for (Future<Object> future : futures)
{
try
{
PingStatus status = (PingStatus)future.get();
// do stuff
}
catch (CancellationException e)
{
// HELP: throw new RuntimeException("Could not ping " + callable.serverName);
}
}
If the timeout is reached, and a CancellationException is throwing on the get, I'd like to throw a new exception that includes the serverName passed into the Callable. What's the best pattern here? And, why doesn't FutureTask provide a reference to the underlying Callable passed in on the constructor?

The original Callable is not retrievable from the Future object due to the separation between the task and the result. There are many methods which would result in Future objects being returned that do not involve the use or creation of Callable objects. Take for instance the method submit(Runnable task) which takes a runnable instead.
Runnable and Callable do not share a common parent superclass meaning that if the future object were to give you the ability to retrieve it, it would have to return an object of type Object. And that is just plain ugly.
Fortunately, if you have read the documentation for the returned list in invokeAll() (emphasis mine):
a list of Futures representing the tasks, in the same sequential order as produced by the iterator for the given task list.
meaning that the order of the input collection of Callable to the returned list of Future is preserved. By this, you can use the current index of Future to work out which Callable was cancelled.
E.g:
futures = executor.invokeAll(callables, TIMEOUT_SECONDS, TimeUnit.SECONDS);
int index = 0; // Index used for for-loop
for (Future<Object> future : futures){
try{
PingStatus status = (PingStatus)future.get();
// do stuff
}catch(CancellationException e){
Callable<Object> offendingCallable = callables.get(index);
// deal with object here
}
index++;
}
As a side note, it seems like you are returning an object PingStatus as a result from the execution. You should thus declare your custom callable as:
public class Ping<PingStatus> implements Callable{
and your appropriate future objects as Future<PingStatus> to avoid nasty casts from Object to PingStatus.

Related

Catch and throw custom Exception from Java ExecutorService

I have a function that goes through a list of HappyObjects and sets their fields asynchronously. In the Callable, a JsonProcessingException can occur. I have to wrap this and other exceptions from this function into a custom exception (ControllerException) and throw that instead.
Other Stack Overflow posts seem to suggest collect into a List of Futures and use get() to catch the exceptions. Thus, this is what I have so far:
default List<HappyObj> fillfunction(final List<HappyObj> happyObjs) throws ControllerException {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
List<Future<HappyObj>> futures = new ArrayList<>();
for (HappyObj happyObj : happyObjs) {
Future<HappyObj> future = executor.submit(
() -> {
final List<Mood> moods = getMoods();
for (Mood mood : moods) {
final String json = getJsonEmotion();
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
List<Emotion> emotions =
mapper.readValue(json, new TypeReference<List<Emotion>>() {}); //JsonProcessingException can occur here
MoodMetadata metadata = mood.getMoodMetadata();
if (metadata != null && metadata.getEmotionMetadata() != null) {
metadata.getEmotionMetadata().setEmotions(emotions);
}
}
happyObj.setMoods(moods);
return happyObj;
});
futures.add(future);
}
executor.shutdown();
final long maxSlaSec = 1;
try {
executor.awaitTermination(maxSlaSec, TimeUnit.SECONDS);
List<HappyObj> happyResult = new ArrayList<>();
for (Future<HappyObj> future : futures) {
happyResult.add(future.get());
}
return happyResult;
} catch (InterruptedException | ExecutionException e) {
executor.shutdownNow();
throw new ControllerException(e);
}
}
Is there a more elegant way than iterating through List<Future> and calling get on each to catch ExecutorException? I thought about using execute() vs. submit(), but then I can't handle the JsonProcessingException. I saw another post suggesting creating a ThreadPoolExecutor subclass and override the afterExecute(), but I wasn't able to handle the JsonProcessingException.
One of the reasons I asked this question is because since this method consists mainly of setters, the function was originally manipulating the given objects and returning void.
According to the docs of ExecutionException (and also the docs of Future#get), it already has wrapped that information. That is, you can use its getCause to inspect the Exception thrown by the Callable's body.
Notice that Callable#call itself throws an Exception... When you throw an Exception from the Callable, it will be wrapped into an ExecutionException which will be thrown from the Future#get method, for each Callable, meaning that you can change your loop to catch an ExecutionException for each Future and inspect its getCause!
So you don't actually need to wrap it to a custom ControllerException.
The Callables you create, can still return null of type Void for example, without needing to do anything about them.
Unless the scenario changes, then you don't need to extend ThreadPoolExecutor in this case. You don't even have to cast to ThreadPoolExecutor, because the ExecutorService interface already has the submits you need. Just throw whatever Exception you need from the Callable (such as JsonProcessingException that you mentioned) when something goes wrong in the Callable, and then inspect the ExecutionException from each Future#get method to tell if an JsonProcessingException was thrown (and you can also determine in which one it was thrown, if you need).
Is there a more elegant way than iterating through List and calling get on each to catch ExecutorException?
In my opinion, no, there is not, because you want to submit all Callables first, then let them run in parallel, and at the end inspect their ExecutionException for any Exception thrown by the Callables' body for each Callable (via Future#get of the returned Future by submit).

How to know if a Future is created with Callable or Runnable

I am dipping my feet in Futures. A Future can be created with a Runnable and with a Callable. Is there a way to decide how it was created?
For example, I have the following code:
Future<?> future = null;
Future<?> future2 = null;
ExecutorService service = null;
service = Executors.newSingleThreadExecutor();
future = service.submit(() -> {
for (int i = 0; i < 5; ++i) {
System.out.println("Printing record: " + i);
Thread.sleep(5);
}
return "Done";
});
future2 = service.submit(() -> System.out.println("Printing zoo inventory"));
System.out.println("================================================================");
System.out.println(future);
System.out.println(future.get().getClass());
System.out.println(future.get());
System.out.println("================================================================");
System.out.println(future2);
try {
System.out.println(future2.get().getClass());
System.out.println(future2.get());
} catch (ExecutionException e) {
System.out.println("Could not do a get");
}
System.out.println("================================================================");
This results in ending with:
================================================================
java.util.concurrent.FutureTask#5caf905d[Completed normally]
class java.lang.String
Done
================================================================
java.util.concurrent.FutureTask#1f32e575[Completed normally]
Exception in thread "main" java.lang.NullPointerException
at ZooInfo.main(ZooInfo.java:56)
I could solve this by using:
if (future2.get() == null) {
System.out.println("Made with a Runnable");
} else {
System.out.println(future2.get().getClass());
System.out.println(future2.get());
}
The problem with this is that when the Runnable still takes some time, I am waiting on the get for nothing. Is there a way to determine if a Future was created with a Runnable, or a Callable without resorting to using get()?
I don't believe that you really need to know whether the Future was created from a Runnable or a Callable.
For one thing, there are more ways than that to create a Future: for example, CompleteableFuture is not created from either; and, more generally, since Future is an interface, one can create instances however you like.
For another: the abstraction of Future is that it is something that gives you a (possibly null) value when it completes, or throws an exception. That's all it is meant to do.
(Also, your current approach of checking for nullity of the return value doesn't work reliably because Callable.call() is allowed to return null).
If you need it to do something else, you may want to revisit your design so you can simply treat it as it is intended.
But if you really do have a use case that does require you to know how it was created, you need to control the creation. Rather than letting callers submit code directly to the executor, wrap in a class like this:
class YourExecutor {
// Initialize in ctor.
private final ExecutorService executor;
FromRunnable submit(Runnable r) {
return new FromRunnable(executor.submit(r));
}
<T> FromCallable<T> submit(Callable<? extends T> c) {
return new FromCallable<>(executor.submit(c));
}
}
where FromRunnable and FromCallable<T> are classes implementing Future<Void> and Future<T> respectively, which delegate all of the methods to another instance of a compatible Future (passed as the constructor parameter).
You can then check the provenance using instanceof; or by some other means, such as extending a common base case or interface which provides a method describing the provenance.
But, just to reiterate, a better approach is to design your code so it doesn't need to know.

JavaFX Task Callable

I was developing a JavaFX app and I was supplying the JavaFX tasks in an ExecutorService submit method. Also I was trying to get the return value of the Task in the return value of the submit in a Future object. Then I discovered that ExecutorService only returns value when you submit a Callable object, and JavaFX Tasks are runnables despite having a call method. so is there any workaround for this problem?
I tried and solved my problem this way but I'm open to suggestions when I don't want to write my own class.
My main method:
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Semaphore semaphore = new Semaphore(1);
List<Integer> list = IntStream.range(0,100).boxed().collect(Collectors.toList());
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){
List<Integer> sendingList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
sendingList.add(iterator.next());
}
System.out.println("SUBMITTING");
Future<Integer> future = executorService.submit((Callable<Integer>) new TestCallable(sendingList,semaphore));
System.out.println(future.get());
semaphore.acquire();
}
executorService.shutdown();
System.out.println("COMPLETED");
}
My TestCallable class:
class TestCallable extends Task<Integer> implements Callable<Integer> {
private Random random = new Random();
private List<Integer> list;
private Semaphore semaphore;
TestCallable(List<Integer> list, Semaphore semaphore) {
this.list = list;
this.semaphore = semaphore;
}
#Override
public Integer call(){
System.out.println("SENDING");
System.out.println(list);
try {
Thread.sleep(1000+random.nextInt(500));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("RECEIVED");
semaphore.release();
return list.size();
}
}
Task extends java.util.concurrent.FutureTask which in turn implements the Future interface. This means you can use a Task just like a Future.
Executor executor = ...;
Task<?> task = ...;
executor.execute(task);
task.get(); // Future method
This will cause the thread calling get() to wait until completion. However, a Task's purpose is to communicate the progress of a background process with the JavaFX Application Thread. It's close relationship to the GUI means you will most likely be launching a Task from the FX thread. This will lead to get() being called on the FX thread which is not what you want as it will freeze the GUI until get() returns; you might as well have just called Task.run directly.
Instead, you should be using the asynchronous functionality provided by Task. If you want to retrieve the value when the Task completes successfully you can use the onSucceeded property or listen to the value/state property. There's also ways to listen for failure/cancellation.
Executor executor = ...;
Task<?> task = ...;
task.setOnSucceeded(event -> handleResult(task.getValue()));
task.setOnFailed(event -> handleException(task.getException()));
executor.execute(task);
If you don't need the functionality provided by Task then it would probably be best to simply use Runnable or Callable directly.
It's not very clear what you want to do here.
Firstly, your Semaphore does nothing because you used Executors.newSingleThreadExecutor(), which already guarantees that only one task can run at any point in time.
Secondly, like what #Slaw mentioned, you are potentially blocking on JavaFX Application thread, depending on your actual implementation (your example isn't really a JavaFX application).
Next, ExecutorService has 2 main overloads for submit().
The first overload takes in a Callable. This overload allows you to retrieve the value returned by the Callable (by calling get() on the returned Future), because Callable refers to something that is can be called - it can return value.
The second overload takes in a Runnable. Since Task implements Future RunnableFuture interface, and Future RunnableFuture interface extends Runnable interface, passing in a Task would be equivalent to calling this overload. This overload does not expect a result to be returned, because Runnable is something that you run without a result. Calling get() on the Future returned by this overload will block until the task finishes, and null will be returned. If you need to retrieve the value returned by the Task, you need to call get() of the Task, not the Future returned by ExecutorService.submit().
Edit based on OP's comments
Firstly, since the calling method is already running in a background thread, and all tasks are expected to run sequentially (instead of parallelly), then you should just run them without all these additional ExecutorService and Task, unless there is another reason why this has to be done.
Secondly, a List object is nothing but an object doing referencing. What could have really affected performance is that you are copying the reference of the elements to the new list. You could have used List.subList()if the indices are known, as the returned list would use the same backing array as the original list, so there isn't an additional O(n) operation for copying.

How to return a value from a lambda expression?

I have a collection (concurrentHashMap) and a method which should work in a separate thread and return numOfApples:
public int getApples(String treeNum) {
int numOfApples = null;
Runnable task = () -> {concurrentHashMap.get(treeNum).getApples(); };
new Thread(task).start() ;
return numOfApples;
}
Is it possible to pass num of apples from lambda expression (concurrentHashMap.get(treeNum).getApples()) to the numOfApples variable?
The problem is not about returning the value from a lambda expression. It is about returning a result from an asynchronous task.
You won't be able to do that easily using a Runnable. You should use a Callable instead, quoting its Javadoc:
A task that returns a result and may throw an exception.
Also, you definitely should not be creating unmanaged raw threads like that: new Thread(task).start();. You should use an ExecutorService and submit the Callable to it.
Consider the following code:
public int getApples(String treeNum) {
Callable<Integer> task = () -> concurrentHashMap.get(treeNum).getApples();
Future<Integer> future = Executors.newCachedThreadPool().submit(task);
return future.get();
}
It creates a Callable<Integer> holding the task returning the number of apples. This task is submitted to an ExecutorService (I simply used a cached thread pool here, you might want another). The result is contained inside a Future<Integer> instance, whose get() method will block, wait for the result and then return it.

When should prefer Callable over Runnable and why?

On SO, I found all theoretical difference between Callable and Runnable and all are almost similar. But, I didn't understand why was Callable introduced in later version ? What was the gap/flaws in Runnable, which Callable is capable of doing ? Anyone can explain with scenario where Callable is only solution ?
Callable has two differences. It can return a value or throw a checked exception.
This make a difference when using lambdas so that even though you don't specify which one to sue the compiler has to work it out.
// the lambda here must be a Callable as it returns an Integer
int result = executor.submit(() -> return 2);
// the lambda here must be a Runnable as it returns nothing
executors.submit(() -> System.out.println("Hello World"));
// the lambda here must be a Callable as an exception could be thrown
executor.submit(() -> {
try (FileWriter out = new FileWriter("out.txt")) {
out.write("Hello World\n");
}
return null; // Callable has to return something
});
Well, the documentation does answer a big part of your question:
The Callable interface is similar to Runnable, in that both are
designed for classes whose instances are potentially executed by
another thread. A Runnable, however, does not return a result and
cannot throw a checked exception.
So, you are jusing Callable instead of Runnable, if...
You need to throw a checked exception or...
You need to return an object (of course you could simulate this by giving your runnable an internal result object, etc. - but it's easier that way)
For example...
ExecutorService service = ... some ExecutorService...;
Callable<Integer> myCallable = new MyCallable( ... some parameters ... );
Future<Integer> future = service.submit( myCallable );
...
Integer myResult = future.get(); // will wait and return return value from callable as soon as done

Categories

Resources