Handle a lot of Futures given by asynchronous rest-requests - java

I wanna use the jersey-client for creating asynchronous rest-requests, the function delivers me Futures, so i can, in my understanding, invoke get, and if the request is finished it will return something.
So i am thinking, i could store the Futures in a map and look into them from time to time by one thread. Or maybe i should create a new thread everytime someone sending an asynchronous request. There is also a requirement that it shouldn't last forever (a timeout).
What do you think?

I often use a List<Future<Void>> to store the futures. As get() blocks, I just cycle through them rather than poll them.
There is also a requirement that it should last forever (a timeout).
I assume you mean its shouldn't last forever. This requires support in the library you are using to make the requests. If they can be interrupted you can cancel(true) the future either in your waiting thread or another ScheduledExecutorService. If they can't be interrupts you may have to stop() the thread but only as a last resort.

The javadoc says:
A Future represents the result of an asynchronous computation. Methods
are provided to check if the computation is complete, to wait for its
completion, and to retrieve the result of the computation. The result
can only be retrieved using method get when the computation has
completed, blocking if necessary until it is ready.
Therefore it is up to you to choose which strategy to adopt: it mostly depends on what you want to do with those requests.
You could place those Futures in any iterable structure before going through them. Block on each get may be a strategy if you can handle each result pretty fast and do need to check while waiting if other futures are already returned.

Related

Java cancel Future - How to wait for finish?

Long story short: I have a collection of Future objects. Some of them are already in progress, some are not. I iterate the collection and call future.cancel(false) which, according to the documentation, should cancel all Futures that are not currently running but should allow all the others to complete.
My question is: How do I know when a particular Future is completed after I have called future.cancel(false)? future.isDone() always returns true because cancel() was indeed called before that and future.get() always throws a CancellationException even though the Future is still running.
Any suggestions?
Since Future models the future result of a pending computation, and since that result is not forthcoming from a canceled future, it is reasonable that Future gives you no way to find out when the computation whose result has been disposed of will complete. In other words, you'd need another paradigm to achieve your goal with that approach.
If your wish is to wait for all the submitted tasks to complete, the closest thing which is directly supported by the Executor Service API is to shut down the entire executor service and wait for its termination.
If the above does not fit your solution, then I don't see a better approach than some custom solution, for example a custom implementation of Runnable, which does some housekeeping on the side so you can check when it has completed running.
You could add a flag to your Future implementation which will reflect the actual Future' state
given a Callable<Object> c:
futureTask1 = new FutureTask<Object>(c);
futureTask2 = new FutureTask<Void>(futureTask1, null);
executor.execute(futureTask2);
now if you want the result:
futureTask1.get()
if you're no longer interested in the result:
futureTask1.cancel(mayInterruptIfRunning)
if you want to wait to be sure the code in the callable is not (and will not become) running (whether never called, finished cancelling or finished producing the result):
futureTask2.get()
Even if cancelled before it started working, this waits for the executor to execute the scheduled task (which will to nothing if already cancelled), so this may unnecessariliy wait for other long-running tasks to complete. YMMV

CompletionService without regular polling

Use case: tasks are generated in one thread, need to be distributed for computation to many threads and finally the generating task shall reap the results and mark the tasks as done.
I found the class ExecutorCompletionService which fits the use case nearly perfectly --- except that I see no good solution for non-idle waiting. Let me explain.
In principle my code would look like
while (true) {
MyTask t = generateNextTask();
if (t!=null) {
completionService.submit(t);
}
MyTask finished;
while (null!=(finished=compService.poll())) {
retireTaks(finished);
}
}
Both, generateNextTask() and completionService.poll() may return null if there are currently no new tasks available and if currently no task has returned from the CompletionService respectively.
In these cases, the loop degenerates into an ugly idle-wait. I could poll() with a timeout or add a Thread.sleep() for the double-null case, but I consider this a bad workaround, because it nevertheless wastes CPU and is not as responsive as possible, due to the wait.
Suppose I replace generateNextTask() by a poll() on a BlockingQueue, is there good way to poll the queue as well as the CompletionService in parallel to be woken up for work on whichever end something becomes available?
Actually this reminds me of Selector. Is something like it available for queues?
You should use CompletionService.take() to wait until the next task completes and retrieve its Future. poll() is the non-blocking version, returning null if no task is currently completed.
Also, your code seems to be inefficient, because you produce and consume tasks one at a time, instead of allowing multiple tasks to be processed in parallel. Consider having a different thread for task generation and for task results consumption.
-- Edit --
I think that given the constraints you mention in your comments, you can't achieve all your requirements.
Requiring the main thread to be producer and consumer, and disallowing any busy loop or timed loop, you can't avoid the scenario where a blocking wait for a task completion takes too long and no other task gets processed in the meanwhile.
Since you "can replace generateNextTask() by a poll() on a BlockingQueue", I assume incoming tasks can be put in a queue by some other thread, and the problem is, you cannot execute take() on 2 queues simultaneously. The solution is to simply put both incoming and finished tasks in the same queue. To differentiate, wrap them in objects of different types, and then check that type in the loop after take().
This solution works, but we can go further. You said you don't want to use 2 threads for handling tasks - then you can use zero threads. Let wrappers implement Runnable and, instead of checking of the type, you just call take().run(). This way your thread become a single-threaded Executor. But we already have an Executor (CompletionService), can we use it? The problem is, handling of incoming and finished tasks should be done serially, not in parallel. So we need SerialExecutor described in api/java/util/concurrent/Executor, which accepts Runnables and executes them serially, but on another executor. This way no thread is wasted.
And finally, you mentioned Selector as possible solution. I must say, it is an outdated approach. Learn dataflow and actor computing. Nice introduction is here. Look at Dataflow4java project of mine, it has MultiPortActorTest.java example, where class Accum does what you need, with all the boilerplate with wrapper Runnables and serial executors hidden in the supporting library.
What you need is a ListenableFuture from Guava. ListenableFutureExplained

Tracking Completed Tasks in ExecutorService

I'm writing an application in Java which uses ExecutorService for running multiple threads.
I wish to submit multiple tasks (thousands at a time) to the Executor as Callables and when done, retrieve their result. The way I'm approaching this is each time I call submit() function, I get a Future which I store in an ArrayList. Later I pass the List to a thread which keeps iterating over it, calling future.get() function with a timeout to see if the task completed. is this the right approach or is to too inefficient?
EDIT --- More info ---
Another problem is that each Callable takes different amount of processing time. So if I simply take the first element out of the List and call get() on it, it will block while results of others may become available and the program will not know. That is why I need to keep iterating with timeouts.
thanks in advance
is this the right approach or is to too inefficient?
This is not the correct approach per se. You are needlessly iterating over ArrayList checking for task completion.
This is very simple: Just use: CompletionService. You can easily wrap your existing executor into it. From JavaDocs:
Producers submit tasks for execution. Consumers take completed tasks
and process their results in the order they complete.
In essence, CompletionService provides a way to get the result back simply by calling take(). It is a blocking function and the caller will block until the results are available.
Note that the call to Future.get will block until the answer is available. So you don't need another thread to iterate over the array list.
See here https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6

Telling the asynchronous job to wait in Java

I have a situation where sometimes (not always) my asynchronous job is not able to process results by the time needed and I have to return some kind of message to the client saying that his request is still being prepared by checking for it in the database.
The request and creating necessary object for it is handled in one database Transaction, the asynchronous process is handled in the different Transaction. I am using ScheduledThreadPoolExecutor by passing the runnable instance to the execute method.
The problems that sometimes the client makes a request and while the his browser is loading my asynchronous job is able to prepare the necessary data for it, but sometimes it isn't.
So my question is: Is there anyway I can tell asynchronous job to wait until the data is ready?
I am afraid that using just a Runnable instance you are not be able to tell the process to wait unless you sleep the Thread for sometime or looping and keep asking for the results which both are bad ideas.
In order to make this happen correctly, you should use a FutureTask for this by passing Callable instance to it's constructor. By overriding your call() method you should tell you transactional handler to do the job.
You also need to have some kind of a task manager which will add the task to the queue and creates a thread pool which takes and processes those tasks. For the queue purpose I would suggest to use for e.g.: LinkedBlockingDeque which accepts the generic type of FutureTask.
Also you should have a map of future tasks mapped by their name or something which takes the FutureTask as a value. In terms of waiting for the results when your Thread is processed the given FutureTask already you have to immediately remove it from the futures map. Then when your client requests you should check: if the futures map contains the task get the FutureTask from it and call futureTask.get() on it. This will wait until the task is finished.
This is just approach with which I would go. Hope this helps.

In Java, how do I wait for all tasks, but halt on first error?

I have a series of concurrent tasks to run. If any one of them fails, I want to interrupt them all and await termination. But assuming none of them fail, I want to wait for all of them to finish.
ExecutorCompletionService seems like almost what I want here, but there doesn't appear to be a way to tell if all of my tasks are done, except by keeping a separate count of the number of tasks. (Note that both of the examples of in the Javadoc for ExecutorCompletionService keep track of the count "n" of the tasks, and use that to determine if the service is finished.)
Am I overlooking something, or do I really have to write this code myself?
Yes, you do need to keep track if you're using an ExecutorCompletionService. Typically, you would call get() on the futures to see if an error occurred. Without iterating over the tasks, how else could you tell that one failed?
If your series of tasks is of a known size, then you should use the second example in the javadoc.
However, if you don't know the number of tasks which you will submit to the CompletionService, then you have a sort of Producer-Consumer problem. One thread is producing tasks and placing them in the ECS, another would be consuming the task futures via take(). A shared Semaphore could be used, allowing the Producer to call release() and the Consumer to call acquire(). Completion semantics would depend on your application, but a volatile or atomic boolean on the producer to indicate that it is done would suffice.
I suggest a Semaphore over wait/notify with poll() because there is a non-deterministic delay between the time a task is produced and the time that task's future is available for consumption. Therefore the consumer and producer needs to be just slightly smarter.

Categories

Resources