I was using an ExecutorService to schedule tasks to be executed in future. After seeing some "odd" behavior where my Callable was getting executed before I called get() on the Future object returned by submitting my Callable to the ExecutorService pool, I read some documentation and found that the submitted task will get executed between the time it gets submitted or at the latest when get() is called on the Future object.
My question - is there any class that would allow Callables to be submitted to it and ONLY executed when get() is called on it? At this point, it seems like just managing the Callables myself and calling call() on them myself when I am ready for them to be executed seems like it'd accomplish what I want, but I wanted to make sure there was no service already implemented that accomplished this.
In short, is there any alternative to ExecutorService that lets me control when Callables submitted to it are called? Note - the time in the future that I want them called is variable and not determined as I may decide not to call them so a ScheduledExecutorService pool won't work here.
Thanks much!
Sounds like you really want to use a Queue<Callable> instead and just poll the queue for tasks.
That way you can submit as many tasks as you like and execute them at your will - one by one.
Related
CompletableFuture allows to provide callbacks for async calls. You can create a long chain of callbacks where each async call will trigger the next one on completion. This is deemed a better way to write async code instead of using Future where you've to block the thread to get the result of first computation before triggering the next one.
I can understand the argument that callback chains in Completable Futures can provide a more readable code but I'm wondering if there's a performance benefit as well to this approach or is it just a syntactic sugar?
For example, consider the following code:
ExecutorService exec = Executors.newSingleThreadExecutor();
CompletableFuture.supplyAsync(this::findAccountNumber, exec)
.thenApply(this::calculateBalance)
.thenApply(this::notifyBalance)
.thenAccept((i)->notifyByEmail())
.join();
In this code, calculateBalance() can't start until findAccountNumber() finishes so essentially calculateBalance() is blocked on findAccountNumber() and so on for the next methods in the callback chain. How is it better than the following (performance-wise):
ExecutorService exec = Executors.newSingleThreadExecutor();
Future<Integer> accountNumberFuture = exec.submit(findAccountNumberCallable);
Integer accountNumber = accountNumberFuture.get();
Future<String> calculateBalanceFuture = exec.submit(calculateBalanceCallable(accountNumber);
....
....
In most cases, you won't notice a difference, but if you want to be able to have a lot of concurrent asynchronous calls waiting something, you'll want to use CompletableFuture.
The reason is that if you simply call get() on a regular Future the Thread and all resources associated with it become blocked until the call returns. If you have many calls your thread pool might get exhausted, or if you use a CachedThreadPool you might cause lots of threads to be created.
With CompletableFuture, an object is stored on the heap which represents where the application should pick up next, as opposed to using the call stack. The guy who built the API has a talk about it over here.
I have several tasks that are being created by some event. I want to execute the last few tasks(suppose 6) always.
I am using a fixed thread pool. But the problem I am facing is that, it uses a blocking queue internally. I want to dequeue the tasks from the blocking queue if there are new tasks coming in, without pushing them to the executor. How can I achieve this? Is there a different approach to this problem?
In order to do what you want, you can use a ScheduledThreadPoolExecutor. And set the flag setRemoveOnCancelPolicy(true).
This executor returns a Future when you call the submit methods. These futures have a cancel() method that you can call when the new request comes in. You can even cancel the tasks that are currently running if you want too.
There's another alternative to call ThreadPoolExecutor.getQueue().clear(), but this is not safe! So please don't try it :)
I am currently modifying an application to use a ScheduledExecutorService in place of a Timer and I used to access the scheduled task with a Map I kept, and it allowed me to cancel() the task as well as accessing it.
With this API it seems that I have to maintain two Maps, one for accessing the tasks and one for the SheduledFuture<?>s returned by schedule() to be able to cancel them.
I read this post but it looks very heavy to implement compared to what I did with a Timer (Only one Map was needed).
This is a simple application that has two tasks that need to be accessed and cancelled.
Is there something I didn't get or are `Executor's not what I need for something this simple?
So you want following:
You want the instance of task submitted as it has some info.
You need ability to cancel the submitted task.
Modify Class definition of your submitted task to have an instance of Future in it. Now when you submit your task to ExecutorService it will return a Future , you can set this Future object in your submitted task object. So now you just need to retain the submitted task and you will info as well as ability to cancel task via future.
This question is Related to List returned from shutdownNow() can not be converted to submitted Runnable
Problem definition
I want to get runtime exception from Runnableand which I can get only using submit() call which returns me Future<?>.
If I use Submit I loose on the functionality which is provided by execute. As I will no longer able to use shutdownNow() to track not started threads.
So Is this true
If I want to catch runnable exception from my task I will never be able to use shutdownnow to find out not started task.
You can use execute() together with Future by using a custom subclass of FutureTask (which is a Runnable). for most Executors, calling submit() just wraps the Runnable/Callable with a FutureTask under the hood. In you custom subclass of FutureTask, keep a reference to the underlying Runnable/Callable and expose a method for returning it. then, when you call shutdownNow(), the returned Runnables should be instances of your custom FutureTask. (it's annoyting that you need to subclass FutureTask to be able to get at the underlying task, but that's the way it is).
If I submit some tasks to an Executor using invokeAll, am I guaranteed that the submitted thread sees all the side effects of the task executions, even if I don't call get() on each of the returned Futures?
From a practical point of view, it would seem that this would be a useful guarantee, but I don't see anything in the javadoc.
More precisely, do all actions in the body of a Callable submitted to an executor happen-before the return from the invokeAll() call?
It's annoying to uselessly call get() on each future, when in fact the return type is Void and no exceptions are thrown - all the work in the happens as side-effects.
From the documentation of ExecutorService:
Actions in a thread prior to the submission of a Runnable or Callable
task to an ExecutorService happen-before any actions taken by that
task, which in turn happen-before the result is retrieved via
Future.get().
As I read this, there is a memory barrier on task submission, so potentially you'd need to call get() on the last task in your list to, but not the others.
However, since calling get() is the only way to determine whether the task completed or threw, I would still call it on every Future, regardless of memory guarantees.
If invokeAny() promises that no tasks are still in execution when invokeAny() returns, this will be the case: all side effects are visible.
In order for invokeAny() to know that all tasks are done, it needs to have synchronized with those threads, meaning that the returning of the functions happens after the tasks completing (and everything that happens in the task). However the API of 'ExecutorSerive' and 'Future.cancel()' does not explicitly say what happens when you cancel a running task (in particular: will cancel() wait with returning until the tasks has stopped running. The fact that after calling cancel(), isDone() must return true, does imply that cancel() will not return until the task has actually finished executing.
One more thing to watch out for is that you will not know if a task ever started execution, when using invokeAny() without inspecting the Future objects.