A timed state machine, does this work? - java

In jave i have a state machine which i need to migrate to automated state changes, in this i mean i need state changes to occur after certan intervals.. for instance after 5 seconds state one, after 10 seconds state 2.
I was thinking of using ;
ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1);
Schedule a task that basically calls a method, which would change state and then schedule another task to change to next state, and so on.
Any ideas?

Need code similar to this:
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleWithFixedDelay(new Runnable() {
public void run() {
// TODO: do something
}
},
0, // no wait and start the 1st one
5, // delay 5 seconds and do the next one
TimeUnit.SECONDS);
You could also look into scheduleAtFixedRate().

Related

Toggle ScheduledExecutorService so its not always running

I'm currently working on a discord bot just to mess around with, but have used SES in the past for other things, but I always struggle to disable/enable the SES, calling ses.shutdown(); does not work and the runnable continues, and if I did shutdown im not sure how to restart it.
Here is my current code...
private final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
protected void startRainbow(Role rle) {
roleRainbow[] colors = roleRainbow.values();
HashMap<String, Integer> map = new HashMap<>();
map.put("loop", 0);
Runnable r = () -> {
if(map.get("loop") >= colors.length) {
map.put("loop", 0);
}
rle.getManager().setColor(Color.decode(colors[map.get("loop")].toString())).queue();
System.out.println("color is: " + colors[map.get("loop")].toString());
System.out.println("color from role: " + rle.getColor());
map.put("loop", map.get("loop") + 1);
};
ses.scheduleAtFixedRate(r, 1L, 1, TimeUnit.SECONDS);
}
There are two angles to this problem:
Interrupting a currently-running thread.
Graceful shut down of a scheduled executor service.
The first has been addressed many many times on Stack Overflow already. In brief: You must signal a thread that you want it to interrupt itself. That thread's task must be coded is such a way to look for the interruption signal.
For the second, there are two steps involved:
You first tell the scheduled executor service that you want to stop any further executions of future-scheduled tasks. We do this with a call to shutdown. This call does not interrupt any currently existing task (see above paragraph).
Alternatively, you may call shutdownNow. This call may signal the running task to interrupt, but no guarantees. The behavior is implementation-defined.
After requesting the service to stop further scheduling, you can watch to see if the service does indeed stop after a reasonable amount of time has passed. We do this with a call to awaitTermination.
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;
ses.scheduleAtFixedRate( task , initialDelay , period , timeUnit ) ;
…
ses.shutdown() ;
boolean terminated = false ;
try { terminated = ses.awaitTermination( 1 , TimeUnit.MINUTES ); } catch ( InterruptedException e ) { e.printStackTrace(); }
if( ! terminated ) { … Houston, we have a problem. … }
The call to shutdown (and shutdownNow) does not block; it does not wait for anything to happen, and does not wait for tasks to end.
The call to awaitTermination does block until either:
Scheduled executor service finishes its last running task, and ends.
The specified time-out elapses.
Test for the boolean returned by the awaitTermination call. To quote the Javadoc:
true if this executor terminated and false if the timeout elapsed before termination
You asked:
if I did shutdown im not sure how to restart it.
Once shutdown, the scheduled executor service is done. To schedule tasks for execution, you must instantiate a new scheduled executor service.
Be aware that a scheduled executor service with no tasks to execute takes very little memory or CPU. So no need to shutdown if you might later need the service.
However, be sure to always shutdown your executor services before your app ends. Otherwise the backing thread pool(s) may continue running indefinitely, like a zombie 🧟‍♂️.

What's the difference between fixed rate and fixed delay in Spring Scheduled annotation?

I am implementing scheduled tasks using Spring, and I see there are two types of config options for time that schedule work again from the last call. What is the difference between these two types?
#Scheduled(fixedDelay = 5000)
public void doJobDelay() {
// do anything
}
#Scheduled(fixedRate = 5000)
public void doJobRate() {
// do anything
}
fixedRate : makes Spring run the task on periodic intervals even if the
last invocation may still be running.
fixedDelay : specifically controls the next execution time when the
last execution finishes.
In code:
#Scheduled(fixedDelay=5000)
public void updateEmployeeInventory(){
System.out.println("employee inventory will be updated once only the last updated finished ");
/**
* add your scheduled job logic here
*/
}
#Scheduled(fixedRate=5000)
public void updateEmployeeInventory(){
System.out.println("employee inventory will be updated every 5 seconds from prior updated has stared, regardless it is finished or not");
/**
* add your scheduled job logic here
*/
}
"fixedRate" : waits for X millis from the start of previous execution before starting next execution. If current execution exceeds 'fixedRate' interval, the next execution is queued and this will create a series of tasks running ie multiple instances of tasks will be running.
private static int i = 0;
#Scheduled(initialDelay=1000, fixedRate=1000)
public void testScheduling() throws InterruptedException {
System.out.println("Started : "+ ++i);
Thread.sleep(4000);
System.out.println("Finished : "+ i);
}
Output:
Started : 1
Finished : 1 // after 4 seconds
Started : 2 // immediately w/o waiting for 1 sec as specified in fixed rate
Finished : 2 // after 4 seconds
and so on
"fixedDelay" : waits for X millis from the end of previous execution before starting next execution. Doesn't matter how much time current execution is taking, the next execution is started after adding 'fixedDelay' interval to end time of current execution. It will not queue next execution.
private static int i = 0;
#Scheduled(initialDelay=1000, fixedDelay=1000)
public void testScheduling() throws InterruptedException {
System.out.println("Started : "+ ++i);
Thread.sleep(4000);
System.out.println("Finished : "+ i);
}
Output:
Started : 1
Finished : 1 // after 4 seconds Started :
2 // waits for 1 second as specified in fixedDelay
Finished : 2 // after 4 seconds
Started : 3 // after 1 second
and so on
fixedRate: This is used to run the scheduled jobs in every n milliseconds. It does not matter whether the job has already finished its previous turn or not.
fixedDelay: It is used to run the scheduled job sequentially with the given n milliseconds delay time between turns. Which means, the time spent on the job will affect the start time of the next run of scheduled job.
fixedRate Example:
#Scheduled(fixedRate = 5000)
public void runJobWithFixedRate() {
...
}
Let's assume the job is triggered at 13:00:00 for the first time:
1st run -> 13:00:00, job finishes at 13:00:02
2nd run -> 13:00:05, job finishes at 13:00:08
3rd run -> 13:00:10, job finishes at 13:00:16
4th run -> 13:00:15, job finishes at 13:00:18
fixedDelay Example:
#Scheduled(fixedDelay = 5000)
public void runJobWithFixedDelay() {
...
}
Let's assume the job is triggered at 13:00:00 for the first time:
1st run -> 13:00:00, job finishes at 13:00:02
2nd run -> 13:00:07, job finishes at 13:00:08
3rd run -> 13:00:13, job finishes at 13:00:16
4th run -> 13:00:21, job finishes at 13:00:25
When to use "fixedRate":
fixedRate is appropriate if it is not expected to exceed the size of the memory and the thread pool. If the incoming tasks do not finish quick, it may end up with "Out of Memory exception"
When to use "fixedDelay":
If every running task is relevant to each other and they need to wait before the previous one finishes, fixedDelay is suitable. If fixedDelay time is set carefully, it will also let the running threads enough time to finish their jobs before the new task starts
One thing which should be clarified is that fixedRate does not mean executions will start with a certain time interval.
If one execution cost too much time (more than the fixed rate), the next execution will only start AFTER the previous one finishes, unless #Async and #EnableAsync are provided. The following source codes which are part of Spring's ThreadPoolTaskScheduler implementation explain why:
#Override
public void run() {
Date actualExecutionTime = new Date();
super.run();
Date completionTime = new Date();
synchronized (this.triggerContextMonitor) {
this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
if (!this.currentFuture.isCancelled()) {
schedule();
}
}
}
You can see that only after the previous task is finished (super.run()), the next task is scheduled (schedule()). With #Async and #EnableAsync, super.run() is an async function which will return immediately, thus the next task does not have to wait for the previous one to actually finish.
We can run a scheduled task using Spring’s #Scheduled annotation but based on the properties fixedDelay and fixedRate the nature of execution changes.
The fixedDelay property makes sure that there is a delay of n
millisecond between the finish time of an execution of a task and
the start time of the next execution of the task.
This property is specifically useful when we need to make sure that only one instance of the task runs all the time. For dependent jobs, it is quite helpful.
The fixedRate property runs the scheduled task at every n
millisecond. It doesn’t check for any previous executions of the
task.
This is useful when all executions of the task are independent. If we don’t expect to exceed the size of the memory and the thread pool, fixedRate should be quite handy.
But, if the incoming tasks do not finish quickly, it’s possible they end up with “Out of Memory exception”.
Fixed Delay : specifically controls the next execution time when the last execution finishes.
Fixed Rate : makes Spring run the task on periodic intervals even if the last invocation may be still running.
There seems to be conflicting advice on what these methods do. Maybe the behavior can change depending on the taskScheduler or Executor bean registered with the spring context. I found #Ammar Akouri's answer to be the most close.
Here's what I found when using a ScheduledThreadPoolExecutor (full test source provided below)
neither fixedDelay nor fixedRate allow concurrent task executions
fixedDelay will wait for the end of a previous invocation, then schedule a new inovcation at a fixed amount of time in the future. It will hence not queue up more than one task at a time.
fixedRate will schedule a new invocation every period. It will queue up more than one task at a time (potentially unbounded) but will never execute tasks concurrently.
Sample Test (Kotlin/JUnit):
class LearningSchedulerTest {
private lateinit var pool: ScheduledExecutorService
#Before
fun before() {
pool = Executors.newScheduledThreadPool(2)
}
#After
fun after() {
pool.shutdown()
}
/**
* See: https://stackoverflow.com/questions/24033208/how-to-prevent-overlapping-schedules-in-spring
*
* The documentation claims: If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
* https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html#scheduleAtFixedRate-java.lang.Runnable-long-long-java.util.concurrent.TimeUnit-
*/
#Test
fun `scheduleAtFixedRate schedules at fixed rate`() {
val task = TaskFixture( initialSleep = 0)
pool.scheduleAtFixedRate({task.run()}, 0, 10, TimeUnit.MILLISECONDS )
Thread.sleep(15)
Assert.assertEquals(2, task.invocations.get())
Thread.sleep(10)
Assert.assertEquals(3, task.invocations.get())
Thread.sleep(10)
// 1 initial and 3 periodic invocations
Assert.assertEquals(4, task.invocations.get())
}
#Test
fun `scheduleAtFixedRate catches up on late invocations`() {
val task = TaskFixture(initialSleep = 30)
pool.scheduleAtFixedRate({task.run()}, 0, 10, TimeUnit.MILLISECONDS )
Thread.sleep(15) // we see no concurrent invocations
Assert.assertEquals(1, task.invocations.get())
Thread.sleep(10) // still no concurrent invocations
Assert.assertEquals(1, task.invocations.get())
Thread.sleep(10)
// 1 initial and 3 periodic invocations
Assert.assertEquals(4, task.invocations.get())
}
#Test
fun `scheduleWithFixedDelay schedules periodically`() {
val task = TaskFixture( initialSleep = 0)
pool.scheduleWithFixedDelay({task.run()}, 0, 10, TimeUnit.MILLISECONDS )
Thread.sleep(35)
// 1 initial and 3 periodic invocations
Assert.assertEquals(4, task.invocations.get())
}
#Test
fun `scheduleWithFixedDelay does not catch up on late invocations`() {
val task = TaskFixture( initialSleep = 30)
pool.scheduleWithFixedDelay({task.run()}, 0, 10, TimeUnit.MILLISECONDS )
Thread.sleep(35)
// 1 initial invocation, no time to wait the specified 10ms for a second invocation
Assert.assertEquals(1, task.invocations.get())
}
class TaskFixture(val initialSleep: Long) {
var invocations = AtomicInteger()
fun run() {
invocations.incrementAndGet()
if (invocations.get() == 1){
Thread.sleep(initialSleep)
}
}
}
}
The fixedDelay property makes sure that there is a delay of n millisecond between the finish time of an execution of a task and the start time of the next execution of the task.
This property is specifically useful when we need to make sure that only one instance of the task runs all the time. For dependent jobs, it is quite helpful.
The fixedRate property runs the scheduled task at every n millisecond. It doesn't check for any previous executions of the task.
This is useful when all executions of the task are independent. If we don't expect to exceed the size of the memory and the thread pool, fixedRate should be quite handy.
But, if the incoming tasks do not finish quickly, it's possible they end up with “Out of Memory exception”.
For more details visit:
https://www.baeldung.com/spring-scheduled-tasks
Several answered have said that fixed rate will run parallel processes if tasks are still running. This seems not true. In this baeldung article they say
In this case, the duration between the end of the last execution and the start of the next execution is fixed. The task always waits until the previous one is finished.
I've tested it myself. Notice the code waits 5 seconds for the job to finish even though the scheduled rate is only 3 seconds.
AtomicInteger runCount = new AtomicInteger(0);
/** Sleeps for 5 seconds but pops every 3 seconds */
#Scheduled(fixedRate = 3000)
public void runTransactionBillingJob() throws InterruptedException {
log.info("{}: Popping", runCount);
Thread.sleep(5000);
log.info("{}: Done", runCount);
runCount.incrementAndGet();
}
Which produces
""10:52:26.003 [pls-scheduled-task-pool-1] INFO c.p.c.s.i.InvoiceSettingsServiceImpl.runTransactionBillingJob 38 - 0: Done
""10:52:26.004 [pls-scheduled-task-pool-1] INFO c.p.c.s.i.InvoiceSettingsServiceImpl.runTransactionBillingJob 36 - 1: Popping
""10:52:31.015 [pls-scheduled-task-pool-1] INFO c.p.c.s.i.InvoiceSettingsServiceImpl.runTransactionBillingJob 38 - 1: Done
""10:52:31.017 [pls-scheduled-task-pool-1] INFO c.p.c.s.i.InvoiceSettingsServiceImpl.runTransactionBillingJob 36 - 2: Popping
""10:52:36.023 [pls-scheduled-task-pool-1] INFO c.p.c.s.i.InvoiceSettingsServiceImpl.runTransactionBillingJob 38 - 2: Done
""10:52:36.024 [pls-scheduled-task-pool-1] INFO c.p.c.s.i.InvoiceSettingsServiceImpl.runTransactionBillingJob 36 - 3: Popping
""10:52:41.032 [pls-scheduled-task-pool-1] INFO c.p.c.s.i.InvoiceSettingsServiceImpl.runTransactionBillingJob 38 - 3: Done
""10:52:41.033 [pls-scheduled-task-pool-1] INFO c.p.c.s.i.InvoiceSettingsServiceImpl.runTransactionBillingJob 36 - 4: Popping

Embeded Jetty, kill Request after a given time

I run a jar with an embedded Jetty. From time to time it happens that one request get stuck in some endless loop. Obviously fixing the endless-loop would be the best option. However, this is currently not possible.
So I am looking for an option, that checks if a request exists for more than e.g. 5 minutes, and kills the corresponding thread.
I tried the typical Jetty options:
maxIdleTime
soLingerTime
stopTimeout
None of them worked as expected. Is there another option to consider?
Do you access to the code that kicks of the code which takes too long to complete? If so you can use callable and an Executor to achieve this yourself, below is a unit test with an example:
#Test
public void timerTest() throws Exception
{
//create an executor
ExecutorService executor = Executors.newFixedThreadPool(10);
//some code to run
Callable callable = () -> {
Thread.sleep(10000); //sleep for 10 seconds
return 123;
};
//run the callable code
Future<Integer> future = (Future<Integer>) executor.submit(callable);
Integer value = future.get(5000, TimeUnit.MILLISECONDS); //this will timeout after 5 seconds
//kill the thread
future.cancel(true);
}

Scheduled Task using ExecutorService

I would like to use ExecutorService in JAVA to schedule the insertion into database every 5 min.
this the task that i want to execute it:
MyClass{
a counter that count a handled data received from a Thread
I receive usually 300 data line/second
Apply a treatment on these data and keep the results in the memory
every five minutes {
update the database with the counters saved in memory*
}
}
Basically it's calling the task each time he get a data from thread running in the background.
and as i have more then 300 data/sec it's impossible to use it in this way.
So what i am trying to do id to handle the received tasks and keep a counter in the memory and update the database only each 5 min.
My question, is it possible to use these java function ScheduledExecutorService to do this, and how can we do it ( i don't want to block my JAVA application on the task for 5min, i want that that application run normally but without executing the task every time, i appreciate if you can show me an example of usage for these function ?
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
service.scheduleAtFixedRate(command, 5, 5, TimeUnit.MINUTES);
Where command is:
Runnable command = new Runnable() {
public void run() {
// update database
}
}

Java: addScheduledJobAfterDelay() - can I force a scheduled job to start?

I'm developing a poker game. On the betting stage I create a scheduled job using Red5 iSchedulingService that will run every 8 seconds to forward to the next player to place a bet. Now if the user placed a bet before the 8 seconds are over, I want to manually force the next scheduled job to start.
Is there a way to force the scheduled job to start immediately when required?
You can do this with Executors. There are cleaner implementations, but this is a stab and something basic that does what you want using Future and Callable.
// wherever you set up the betting stage
ScheduledExecutorService bettingExecutor =
Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> future = bettingExecutor.schedule(new BettingStage(), 8,
TimeUnit.SECONDS);
//...
// in the same class (or elsewhere as a default/protected/public class)
private class BettingStage implements Callable<ScheduledFuture<?>> () {
public ScheduledFuture<?> call() thows ExecutionException {
ScheduledFuture<?> future = bettingExecutor.schedule(new BettingStage(), 8,
TimeUnit.SECONDS);
// betting code here
boolean canceled = future.cancel(false); // cancels the task if not running yet
if(canceled) {
// run immediately
future = bettingExecutor.schedule(new BettingStage(),
0, TimeUnit.SECONDS)
}
return future;
}
}
an answer to my specific question that I started with in this thread:
i cannot force to start a scheduled job, but what I can do is remove the scheduled job and start a new job with a delay of 0 seconds.
addScheduledJobAfterDelay() return a string that represents the job id. i can use it to remove the scheduled job. The problem is that there is no way to know if I'm interrupting the scheduled job or not. Executors do provide that information. that is why Executors are better choice in this specific case then using the red5 scheduling service.
how to remove a scheduled job (red5):
ISchedulingService scheduler = (ISchedulingService) getScope().getContext().getBean(ISchedulingService.BEAN_NAME);
scheduler.removeScheduledJob("ScheduleJobString");
the string ScheduleJobString should be replaced with the string that you have received from creating the job:
String scheduleJobString = scheduler.addScheduledOnceJob(DelayInSeconds*1000,new MyJob());

Categories

Resources