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());
Related
It's the first time I use Java for a project and I need to do this:
send a CoAP POST request to turn on an actuator
wait 10 seconds
send a CoAP POST request to turn off the actuator.
I'm using this code inside the method I wrote that has to automatically turn on/off the actuator:
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run (){
Request postRequest2 = new Request(CoAP.Code.POST);
postRequest2.setURI(String.format("%s%s", COAP_ENDPOINT1, targetStatusActuatorUri));
postRequest2.setConfirmable(true);
}
},
10000
);
But it throws an error Unreachable statement and I don't understand why.
As commented, you need to supply more debugging details.
ScheduledExecutorService
More generally, I can say that Timer and TimerTask classes were years ago supplanted by the Executors framework. Their Javadoc so notes.
A ScheduledExecutorService allows you to specify a delay before executing your task. Establish the service, and keep it around for later use.
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor() ;
Define your task as a Runnable (or Callable).
Runnable task = () -> {
turnOffActuator() ;
};
In your business logic, turn on the actuator, then assign the turning-off task to the executor while scheduling with a delay.
turnOnActuator() ;
ses.schedule( task , 10 , TimeUnit.SECONDS ) ;
Be sure to eventually shut down your executor service before your app ends/exits. Otherwise the pool of threads backing your executor service may continue running indefinitely, like a zombie 🧟♂️.
All of this has been covered many times already on Stack Overflow. Search to learn more.
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 🧟♂️.
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);
}
Can anyone tell,advice how to run a scheduler without Quartz in java. I want to implement such features that if application server remain stop , my scheduler will run. So I thought the executable class to place outside of the war file. So can anyone give me suggestion ? Thanks.
Regarding scheduling tasks without Quartz, you can use Java's ScheduledExecutorService:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable beeper = new Runnable() {
public void run() { System.out.println("beep"); }
};
// Beeps every 10 seconds
scheduler.scheduleAtFixedRate(beeper, 0, 10, TimeUnit.SECONDS);
Now, regarding doing it when your application is not running, I see three options:
Develop a stand-alone application with your scheduled tasks, decoupled from your webapp
Look up for Application Server features for that purpose
OS scheduled tasks, as Linux's cron job
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().