Scheduled Thread Pool with timeout - possible approaches - java

I know #Synchronized in spring-boot (spring boot is my base technology). However, it can't allow me to set timeout for scheduled funtion.
I heard about java 8 concurrent features, but I am not sure if it can help me.
To sum up:
Periodical (at each 0.5s) execution thread from some limited thread pool and possibility of timeout this scheduled tread.
Any ideas ?

Consider ScheduledThreadPoolExecutor
scheduleAtFixedRate() lets you schedule tasks to be executed after a specified delay and executed again based on the period you specified.
scheduleWithFixedDelay() lets you create tasks that will be executed after the initial delay and then subsequently with provided delay between the termination of last execution and start of another execution.

Related

Configure a threadpool for scheduling tasks and their cancellations also

In our current service architecture, we have a single scheduled threadpool, that is used for executing some computation tasks (for real-time data gathering). These tasks are time-bound, so in case they don't complete in a set amount of time, they are interrupted by scheduling cancellation tasks, which are submitted along with the original tasks. The issue we're seeing is that the cancellations are not always on time, and that some of the tasks can take longer to be cancelled than expected.
According to me, this could be because we are using a common threadpool, where sometimes the cancellation tasks are not getting picked up on time. But I'm not sure about this. Is there a way to confirm this, or find the actual cause of the delays in cancellations?
- they are interrupted by scheduling cancellation tasks
you have scheduled a task to interrupt the original on a scheduled threadpool ?
If so, I think the scheduled thread pool guarantees to wait at least for the delay period. Ie there is no guarantee it will run after precisely the delay period.

Using a ScheduledThreadPool with parallel execution

Currently, I have an application that collects data every second and sends it to an API endpoint. To run every second, I am using a ScheduledThreadPoolExecutor that runs the thread which sends the data. The issue is the sending of the data sometimes takes more than one second, and this results in the next sequence of data to be collected more than a second later. Is there any way this can be changed (or other libraries can be used) so that even if a thread is not finished sending the data, another thread can start running in parallel?
The usual way to deal with the desire for overlapping executions of the same scheduled task is to execute the (time consuming) business logic of the task asynchronously.
In other words, when the once-per-second task is triggered, submit the real work to an ExecutorService (either the one you are using for the scheduled tasks or another one). This way, the scheduled task has already finished it's work (to queue the actual work) long before it is time for it to execute again.
Separate out the data collection and send tasks.
Data collection on a separate Thread pool (or a scheduled single thread) and submit the data to another pool whose job is to publish the data
Assuming you are not concerned about out of order invocations on the "API endpoint" then you can create the ScheduledThreadPoolExecutor with a corePoolSize > 1. In this way, every time the scheduler kicks in it will use the first available thread in the pool. And given a corePoolSize > 1 you would need several invocations to take more than 1s before you'd run out of threads.
For additional context: a ScheduledThreadPoolExecutor has a scheduling thread which checks for tasks and on finding one it delegates the task to a worker thread from its internal pool. If the internal pool has a single thread (i.e. corePoolSize=1) then all tasks are executed seriallly and you cannot guarantee that the tasks will be executed every _wait_period_ (though you can be certain about ordering). If you want to insist on the tasks running on schedule and you are not concerned about ordering then you can configure the pool with a corePoolSize which ensures that there is always an available thread in the 'worker' pool every time the scheduler finds a task.
Edit 1: if you are using scheduleAtFixedRate then the other answer which refers to delegating the scheduled invocation to a separate thread pool is an option. If you adopt this approach then corePoolSize=1 will be sufficient since the 'worker' thread is then only reponsible for delegating the task to a separate pool.

Running method using Spring #Scheduled annotation

I have a a single method annotated with the #Scheduled annotation in Spring, scheduled to run every 2 seconds.
#Schedule(fixedDelay=2000)
public void myOperation() {
...
Thread.sleep(1000);
...
...
Thread.sleep(1000);
}
However, the underling operations being done have sleep() introduced in order to have delays (for a specific use case). Now if the delays add up to more than 2 seconds, I am trying to understand if Spring will spin up a new thread for the next scheduled operation? Or would it wait till the current thread finishes executing and then start the new one?
Also, to prevent the number of threads from exploding to a large amount, is it safe to provide a thread pool size so that there's no sudden increase in the number of threads running?
Using fixedDelay you are specifying the time to wait since the process has finished until start it again. If your process sleeps in between it does not matter. It needs to finish to the fixedDelay time starts counting. So, you are going to have only one thread active in this case.
On the other hand, if want to start a process every two seconds, without considering whether the previous task has finish or not, you need to use fixedRate. In this case, if you want to be sure there are not more than X process running at the same time, you should use a ThreadPoolTaskScheduler.
Have a look to the documentation:
Annotation Type Scheduled
ThreadPoolTaskScheduler
If You want to have scheduled tasks and control threads by yourself, than it's better to use ScheduledPoolExecutor

Maintaining a single executor service and shutting it down appropriately

My application requires that a certain job be done asynchronously, so I've resorted to the executor framework. This job (a Runnable) is expected to be run should a certain external interface be down (the vendor could be backed up for a while, say, 30 mins).
With this ask in mind, I believe I should maintain a single scheduled executor service with a fixed no. of core threads that perform these jobs when the interface I said above goes down for a brief moment (as a static variable in the class I need the thread pool in). I also don't think I should create an executor for every need to handle such a job (single scheduled thread pool executor), and shut down after a job is run, because that would defeat my purpose, wouldn't it? Because that could mean reserving a thread for every job during the backed up hour which sounds scary to me.
But, if I were to maintain such a single executor service, when would I be shutting down the executor? I understand that an executor once shut down can't be reused, while not shutting down the executor and keeping threads active could prevent the JVM from shutting down. How do I go about this?
My last statement was based on this from Effective Java 2nd edition:
And here is how to tell the executor to terminate gracefully (if you
fail to do this, it is likely that your VM will not exit):
executor.shutdown();
This job (a Runnable) is expected to be run should a certain external
interface be down (the vendor could be backed up for a while, say, 30
mins).
Above is your requirement. Now the solution entirely depends on how above situation is handled.
Trigger or event listener: If you have some trigger or event listener which can be called when it is found that a certain external interface is down, then in the that triggered code or event listener, you can create a ExecutorService, execute all your tasks (you can choose on fixed or pooled thread pool), and then on completion of all tasks, you can shutdown the ExecutorService
In this case, it is a good idea to create a ExecutorService, do tasks and shut it down. No need of long running ExecutorService.
Track or periodic check: If you have to track or check periodically whether certain external interface is down or not, then I think you can have a ScheduledThreadPoolExecutor implementation to have check after fixed time interval whether certain external interface is down or not, and if it is down then execute all your tasks. In this case you will NOT shutdown your ExecutorService and it will always be running.
Check scheduleAtFixedRate and scheduleWithFixedDelay for periodic task scheduling.
P.S.: Trigger and Track are my own convention I used tangentially as one word, so do infer it in technical words.
I understand that an executor once shut down can't be reused, while
not shutting down the executor and keeping threads active could
prevent the JVM from shutting down.
Yes, an executor once shut down can't be reused.
No, a running ExecutorService will not stop you JVM shutdown, but once JVM is shutdown that ExecutorService instance and its thread pool will be stopped and destroyed.

scheduleAtFixedRate not starting the task at specified delay

I am using SchedulerExecuterService to execute a task after specified delay and at given intervals.
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(taskThread,60 ,120 ,TimeUnit.SECONDS);
What happening is first time taskThread is not starting after delay of 60 sec, it is started after delay of more than 60 secs. Whereas the next executions started at correct intervals of 120 secs(not exactly 120 secs but there is a very minute delay which can be ignored).
My query is why the first execution is delayed for more than 60 secs? Since the task is executed by a thread, Does the start up time depends on the thread priority?
How can I make it run at exact delay of 60 secs? What about Quartz library? Will this library solve my purpose(run the job at specific time without any delay)?
Thanks in advance.
Startup of a job depends on the scheduled time and the amount of threads available - if there are none available, it can be delayed. However, further executions will start at a scheduled time (delay + n * period) - which is takes place in your case.
Start will happen approximately at a scheduled time, I doubt there are real-time guarantees for this, it depends on the underlying OS. You could try changing a thread priority for a thread in this thread pool. This could help, but it won't give you a guarantee that it would work out in different environment.
You could also make sure you run a single task for a fixed thread pool of a single thread you use. Or try increasing the thread amount.
T.b.h. the delay you are seeing is unlikely to be ScheduledExecutorService's fault. Starting a thread won't take a second unless your machine is ridiculously overloaded, and I think the thread will get initialised up-front anyways if you use a fixed size thread pool.
I'm guessing it's the initialisation of your own tasks. I don't know what you are doing in your task, but getting the resource ready (starting DB connection pools) etc. can amount to significant time.
If you want you can test with a trivial task (like writing "hello" on the console) to see. And then you can measure each part of your task to see what's taking long. Once you have that you can think of ways to "warm" your system to prevent the delay.

Categories

Resources