Should I use #Scheduled or sleep in rest controller? - java

I need to invoke some delayed action after calling my rest controller from frontend. For example after calling endpoint /controller with method Update. I want to get response status OK and in the controller call scheduler which will execute some update function on my entities in database after 15 minutes after call endpoint only once. I just want to simple change 2 boolean fields with delay. What should I use? #Schedule annotation or just sleep or maybe something else? I would be grateful for all advices.
Best regards!

#Scheduled is meant for periodic execution of a certain method. For what you want you should use the ScheduledExecutor class. See the documentation for more details https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
It has two methods, the scheduleWithFixedDelay method is the one you want to use.
EDIT: Heres an example
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
//Do you database save here
}
}, 0, 15, TimeUnit.MINUTES);
EDIT 2:
Maybe its simpler to just use the schedule() method instead, since you are only doing one update. The example above is for when you have multiple actions that must each be done successively with a fixed delay of 15 minuten between executions. For only one execution you could use:
executorService.schedule(() -> database.save(), 15, TimeUnit.MINUTES);
executorService.shutdown();
the code () -> database.save() is called a lambda expression.
calling shutdown after the schedule call is important or else you might get memory leaks. The shutdown() method will wait for the thread in the executorService queue to be executed after which it will destroy the thread used.

Related

Advice for an asynchronous programming problem in Java

I have a set of classes which encapsulate a unit of work on Google Sheets. After the class's execute method is called, they pass a request to a service, bundled with a callback which the service should call on task completion. (As the tasks are non-critical and repeated frequently, the service just logs errors and does not call the class back if its request fails).
Stripped down, the tasks look like this:
public void execute() {
//preparatory stuff, then...
Request r = new Request(this::callback);
service.execute(r);
}
public void callback(Result result) {
...
}
The call to the service is synchronous but within the service, the Request is queued, executed asynchronously, and the callback is invoked on a new thread. Some of the tasks involve several service invocations, the callback methods may themselves create a Request with a second callback method and invoke the service again. I want that to be invisible to client code.
My problem now is that I would like to run the tasks asynchronously from client code and then execute an arbitrary handler after they are done. One way to do this would be to give the class a callback in the execute() method for it to call once execution is complete. But I'd really rather be able to do this inline in code, this sort of thing:
CompletableFuture.supplyAsync(() -> (new Task()).execute()).whenComplete((result, error) -> {});
The problem with that is, the completion of the execute() method does not signal the end of the task, as the task is still awaiting its callback. The other thing is, that callback might never arrive. I can't figure out how I should go about calling the task such that I can run it asynchronously and inline like in the code above and the whenComplete() will be invoked when the Task class explicitly decides it is finished. I'd also need a timeout, as the tasks's callback may not be invoked.
Any ideas? Note that I control the service invoked by the tasks, so I can change how that works if necessary, but I'd probably rather not.
I'd spend some time looking around in java.util.concurrent. Can't you just use an ExecutorService for a lot of this? You can submit() Callable code and get a future back, you can submit a list of Callables and give a timeout, you can call shutdown() and then awaitTermination() to wait for the processing to stop. You can get these notification callbacks by just submitting a Callable that constructs with the callback interface and invokes it when it feelsl like it's done.
Failing this, you might look at actors. Your concurrency pattern would likely be very easy in the actor model.
Going to answer my own question here: I just altered the task execute methods to return a CompletableFuture<TaskResult> with TaskResult containing the desired information. The task stores the CompletableFuture internally and calls complete() as needed in later callbacks. Not sure why I had trouble seeing this solution.

ScheduledThreadPoolExecutor executeNow();

How can I tell ScheduledThreadPoolExecutor(let's call him sht) to execute his task when a button is pressed ?
For example if I have something like this :
sht.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
method1();
method2();
method3();
}
}, 0, 5, TimeUnit.MINUTES);
The methods that are inside sht will execute every 5 minutes but what I want to do is to run them "at now" . I can't just call the methods because some reasons.
I need something like this :
sht.executeNow();
The base execute() method of the Executor interface allows queuing tasks for immediate execution. You should hold a reference to the scheduled Runnable task and submit it for immediate execution on the click of the button.
In case you want to reset the scheduling after the button is clicked, you can do that by removing the previous Runnable task via the remove() method and rescheduling it. The execute() method would not be needed in that case, as you can achieve immediate execution by specifying an initial delay value of 0 in your scheduling method.
Considering your simple use-case, you might want to look at using a Timer instead of ScheduledThreadPoolExecutor, as it provides a much simpler API for what you are attempting. In fact, unless you really need to run these tasks in another Thread, you should use a Handler, which will manage the scheduling and execution of the tasks without needing to start new Threads.

ScheduledExecutorService scheduleWithFixedDelay for Callable

I am trying to execute a periodic action using Java Concurrency package and I am using the following code:
ScheduledExecutorService daemon = Executors.newScheduledThreadPool(1);
daemon.scheduleWithFixedDelay(new AddressThread(ParentMap.getSingletonInstance(), dictionary, test),10, 10, TimeUnit.SECONDS);
where AddressThread is a Runnable type that is passed. The code executes run() every 10 seconds and it is working as I expect. However, I need to return a value and run() does not let me do that. Is there a similar method like scheduleWithFixedDelay where I can pass a Callable interface rather than a Runnable and return something back? If not, how can I do equivalent stuff like above if I want to return a value?
The problem is where do you want to process the result. If your task is executed once you will get the result of the task from the returned ScheduledFuture (see here: here)
When you have several calls noone is able to distinguish when the return value is available.
You could either implement a Listener and call it at the end of your task, our you have a seperate thread, that waits until the result is available, processes it and then schedules the next execution.

Java's FutureTask composability

I try to work with Java's FutureTask, Future, Runnable, Callable and ExecutorService types.
What is the best practice to compose those building blocks?
Given that I have multiple FutureTasks and and I want to execute them in sequence.
Ofcourse I could make another FutureTask which is submitting / waiting for result for each subtask in sequence, but I want to avoid blocking calls.
Another option would be to let those subtasks invoke a callback when they complete, and schedule the next task in the callback. But going that route, how to I create a proper outer FutureTask object which also handles exceptions in the subtask without producing that much of a boilerplate?
Do I miss something here?
Very important thing, though usually not described in tutorials:
Runnables to be executed on an ExecutorService should not block. This is because each blocking switches off a working thread, and if ExecutorService has limited number of working threads, there is a risk to fall into deadlock (thread starvation), and if ExecutorService has unlimited number of working threads, then there is a risk to run out of memory. Blocking operations in the tasks simply destroy all advantages of ExecutorService, so use blocking operations on usual threads only.
FutureTask.get() is blocking operation, so can be used on ordinary threads and not from an ExecutorService task. That is, it cannot serve as a building block, but only to deliver result of execution to the master thread.
Right approach to build execution from tasks is to start next task when all input data for the next task is ready, so that the task do not have to block waiting for input data. So you need a kind of a gate which stores intermediate results and starts new task when all arguments have arrived. Thus tasks do not bother explicitly to start other tasks. So a gate, which consists of input sockets for arguments and a Runnable to compute them, can be considered as a right building block for computations on ExcutorServices.
This approach is called dataflow or workflow (if gates cannot be created dynamically).
Actor frameworks like Akka use this approach but are limited in the fact that an actor is a gate with single input socket.
I have written a true dataflow library published at https://github.com/rfqu/df4j.
I tried to do something similar with a ScheduledFuture, trying to cause a delay before things were displayed to the user. This is what I come up with, simply use the same ScheduledFuture for all your 'delays'. The code was:
public static final ScheduledExecutorService scheduler = Executors
.newScheduledThreadPool(1);
public ScheduledFuture delay = null;
delay = scheduler.schedule(new Runnable() {
#Override
public void run() {
//do something
}
}, 1000, TimeUnit.MILLISECONDS);
delay = scheduler.schedule(new Runnable() {
#Override
public void run() {
//do something else
}
}, 2000, TimeUnit.MILLISECONDS);
Hope this helps
Andy
The usual approach is to:
Decide about ExecutorService (which type, how many threads).
Decide about the task queue (for how long it could be non-blocking).
If you have some external code that waits for the task result:
* Submit tasks as Callables (this is non blocking as long as you do not run out of the queue).
* Call get on the Future.
If you want some actions to be taken automatically after the task is finished:
You can submit as Callables or Runnables.
Just add that you need to do at the end as the last code inside the task. Use
Activity.runOnUIThread these final actions need to modify GUI.
Normally, you should not actively check when you can submit one more task or schedule callback in order just to submit them. The thread queue (blocking, if preferred) will handle this for you.

java Callable FutureTask Excecuter: How to listen to finished task

I'm quite new to executer services. Liked doing everything myself, but I think it's time to trust these services.
I want to hand by Executer a Runnable. The executer wraps that in a FutureTask and hands it back to me. Now I call poll the done() method. But I would like to be notified when then done() method would return true.
There is a get() method that blocks until the Runnable has finished, but then I would need a extra thread for every job, just to see when it's finished.
Can I hand my executer some extra Callable to get notified about the task finishing?
What's the way to go here? I could add some code to the end of the run method, but then done() might still be false...
ExecutorCompletionService
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html
If you want to do one task after another its better to do it in the same thread.
Executor executor =
final Runnable runnable =
executor.execute(new Runnable() {
public void run() {
runnable.run();
// do something after the run() has finished.
}
});
This way it will do whatever you want done after the runnable in the same thread and you don't need to poll or use another thread.
I'd advise taking a look at the com.google.common.util.concurrent package in Guava, specifically the ListenableFuture type and the code related to it.
Once the next release (r10) is out, it'll be easy to create an ExecutorService that returns ListenableFutures using MoreExecutors.listeningDecorator(ExecutorService). You can also currently wrap your Runnables/Callables in a ListenableFutureTask yourself.
final ListenableFutureTask<?> task = new ListenableFutureTask<Object>(
runnable, null);
executor.submit(task);
task.addListener(new Runnable() {
public void run() {
// do whatever
}
}, listenerExecutor);
If you can make a specific assumption of using a java.util.concurrent.ThreadPoolExecutor, then you can use its hook methods; afterExecute() and beforeExecute().
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
They are not as elegant as the ListenableFuture, but it might be an adequate solution provided you need only one type of a "listener" for a given executor instance.

Categories

Resources