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.
Related
I'm trying to gather specific data on how long a task waits between being submitted and actually being executed. The idea is to be able to closely monitor the existing threadpool and tasks that are submitted for execution.
Let's assume I have an ExecutorService with a fixedThreadPool.
I'm also using a composition of completableFutures to perform a set of tasks asynchronously.
I'd like to be able to track within my logs the exact time a certain task had to wait in the queue before being taken for execution.
The way I see it I need two things:
A way to label CompletableFuture (or the Supplier functions passed to CompletableFuture.supplyAsync())
This I could potentially do by providing a wrapper method for the Supplier as mentioned here https://stackoverflow.com/a/57888886 and overwrite the CompletableFuture.supplyAsync() method so it will internally log which named supplier was provided
A way to monitor the time between the submission and execution of a specific Runnable to the threadpool executor.
This I can achieve by extending the ThreadPoolExecutorand providing some custom logging in the beforeExecute() and execute() method
What I'm kind of 'stuck' on now is linking both of them together. The beforeExecute() method override gives me the thread and the runnable - but the thread in itself doesn't tell me much yet, and the runnable isn't named in any way so I can't really know which exact task is taken for execution. Of course I can add additional logs in the task implementations themselves and then assume that they will be right next to the log from beforeExecute(). The problem still remains for execute() itself, since that one is called internally after using the CompletableFuture composition.
So how can I properly link the information from the executor service, with some labelling of the exact tasks provided as CompletableFutures as in the example below?
List<Foo> results = createResults();
results.forEach(r -> CompletableFuture.completedFuture(r)
.thenCompose(result -> addSomething(result, something)
.thenCombine(addSomethingElse(result, somethingElse), (r1, r2) -> result)
.thenCompose(r -> doSomething(result).thenCompose(this::setSomething))
.thenApply(v -> result))));
...
// At some point join() is called to actually wait for execution and completion
listOfFutures.join()
And each of the functions called within return a CompletableFuture<Foo> created by:
private CompletableFuture<Foo> setSomething(Foo foo) {
return CompletableFuture.supplyAsync(() -> {
foo.description = "Setting something";
return foo;
}, myExecutorService);
}
So even by wrapping the Supplier<T> to have it labeled, how am I able to link this with the tracking within the execute() and beforeExecute() method of the ThreadPoolExecutor when that one operates on Runnables instead of Suppliers?
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.
I'm using executor service with newSingleThreadExecutor to execute my Runnable task in serial order, however seems to be serial execution order is not guaranteed, as sometime tasks are executed in random order.
executorService = Executors.newSingleThreadExecutor();
executorService.submit(MyTask1);
executorService.submit(MyTask2);
MyTask performs some Asynchronous operation and send the result back to the class from where I'm executing the task.
though docs says, with newSingleThreadExecutor () tasks has to be executed serially,Im not able to find out what I'm missing here.any help would be appreciated.
Thanks
Since execution order is guaranteed to be sequential, you are problably not using a single thread executor in the code you are actually running.
As a work around, submit one task that does two things:
executorService.submit(() -> {MyTask1.run(); MyTask2.run();});
tl;dr
If the results you are watching arrive out-of-order are being produced asynchronously, then all is well. Async work is being done on its own separate timeline. By definition, the async work launched by task # 1 may not complete until long after tasks # 1, 2, & 3 are all done (for example).
Asynchronous means “don’t wait for me”
You mentioned:
MyTask performs some Asynchronous operation
Asynchronous execution means the calling code need not wait for the async operation to complete.
The calling code, your task submitted to the executor service, makes the request for async work to be done, and the task immediately continues. If that task has no further work, the task is complete. So the executor service can move on.
The executor service moves on. The executor service executes the second submitted task. Meanwhile, the async work requested above may not yet be done. Perhaps the async work is waiting on a resource such waiting for a call over the network to return, or the async work is waiting for a database query to execute. That, by definition of asynchronous, does not block the task submitted to the executor. The executor service is now running the 2nd submitted task, and may be a third or fourth, before, finally, your async work completes.
Feature, not a bug
In other words, a feature, not a bug. The ExecutorService returned by Executors.newSingleThreadExecutor() fulfilled its promise that “Tasks are guaranteed to execute sequentially”. The fact that as a by-product one of those tasks spins off async work does not change the fact that the tasks as submitted were indeed executed in their sequential order.
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.
I have a background task that I run using the ScheduledThreadPoolExecutor with code like this.
executor.scheduleWithFixedDelay(new BackgroundSync(), 0, 15, TimeUnit.MINUTES);
BackgroundSync implements Runnable.
Sometimes from a user event I want the delayed event to run now and not when the 15 minute timer goes off.
Some requirements:
There should only be one "BackgroundSync" running at a time
Based off an user event I should be able to schedule a BackgroundSync immediately IF its not running already.
scheduleWithFixedDelay returns a ScheduledFuture. When calling it, store this somewhere and check if it exists if you want to do the immediate execution. Then you can cancel the scheduled future using the cancel method and schedule your runnable again for immediate execution.
Kabuko's solution is probably as good as you will get, but there is a snag.
The cancel() method returns true if the task was cancelled before it started, and false if the task has already run, or if it was previously cancelled. The problem is that if the task is currently running, cancel() will return true. Thus you need to implement some other mechanism to decide whether or not to resubmit the task.