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.
Related
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);
}
This question already has answers here:
How to run a background task in a servlet based web application?
(5 answers)
Closed 8 years ago.
Have to call the servlet periodically.(like service concept in andorid)
How to do this. Using timer or any other solution?
Thanks in advance.
To expand on the comments by JB Nizet…
The formerly accepted answer is kind of a hack. If the goal is to get some regular task to be performed as part of your web app, Java provides a crew slick technologies to make this happen.
ServletContextListener
The first is a hook defined by the Servlet spec to have code invoked when a web app is deployed and when a web app is shutting down. This hook is the ServletContextListener.
ScheduledExecutorService
The second piece is the executor service added to recent versions of Java as a more sophisticated alternative to the old Timer class. In particular you need the ScheduledExecutorService.
So when your web app start up, the ServletContextListener launches a ScheduledExecutorService. When the ServletContextListener is informed of a shutdown, it tells the executor to gracefully quit.
One trick to this: Be sure to capture all exceptions in your executor. If an exception leaks, the executor silently stops executing. This is a feature not a bug. Read the doc and study up with some googling.
Jakarta Concurrency
Some Servlet containers support Jakarta Concurrency. This specification provides for automatic management of the executor services discussed above.
You can use ,
response.addHeader("Refresh", "5");
"5" denotes 5 seconds .The response.addHeader("Refresh", "5") call adds a response header that is sent back to the client indicating that the browser should make another request of the servlet after 5 seconds.
Same thing can be done using html too,
<meta http-equiv="refresh" content="5" />
you can aslo pass the url here as ,
<meta http-equiv="refresh" content="5" url="example.com"/>
Also have a look at here ..
If you use Java EE 6, an EJB can be packaged in the war, and you can use a #Schedule annotated EJB.
It will be executed periodically, you don't have to do anything else (run threads, or sleep).
You can do this using Java Threads.
Schedule a servlet to load on server startup. See How can I set a servlet to load on startup of the container, rather than on the first request?
In this servlet's init() method, spawn a thread.
In this thread's run() method, calculate the number of milliseconds to wait until the task should be performed. Then call Thread.sleep(msec). Then do the task, and loop (infinitely).
The java.util.Timer class can help a lot.
Use the schedule() method of the java.util.Timer class:
long now = System.currentTimeMillis();
Date whenToRun = new Date(now+millisecondsInFuture);
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
// job code here
}
};
timer.schedule(task, whenToRun);
Or use the scheduleAtFixedRate() method of the java.util.Timer class:
int initialDelay = 30000; // start after 30 seconds
int period = 5000; // repeat every 5 seconds
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
// job code here
}
};
timer.scheduleAtFixedRate(task, initialDelay, period);
How can I create a timeout for each command that is running in parallel using java.​util.​concurrent.ExecutorService?
My code is something like this:
For example in the code below I need obj1 run for maximum 1 min, and obj2 for 2 mins and others 5 mins.
ExecutorService exService;
exService = Executors.newCachedThreadPool();
exService.execute(obj1);
exService.execute(obj2);
exService.execute(obj3);
exService.execute(obj4);
exService.shutdown();
boolean finshed = exService.awaitTermination(5, TimeUnit.MINUTES);
if (finshed) {
//Doing something
}
EDIT:
Unfortunately the class of obj1 - obj4 is scraping some web pages using WebHarvest that uses jakarta HttpClient for reading web pages and HttpClient (And neither WebHarvest itself) doesn't have any feature for timeout on entire page reading and/or scraping job.
This is my time consuming task and I thought about killing ExecutorService thread after a timeout to handle this problem.
In general, there is no reliable way to make a separate thread quit. In particular, there is no reliable way to interrupt and stop your task after a timeout from outside that task. What you need to do is make the tasks themselves responsible for stopping after their time runs out. Depending on what they do, you might be able to abstract this behaviour into a superclass something like:
public abstract class TimeoutRunnable implements Runnable {
private final long timeLimitMillis;
private long startTimeMillis;
public TimeoutRunnable(long timeLimitMillis) {
this.timeLimitMillis = timeLimitMillis;
}
public final void run() {
startTimeMillis = System.currentTimeMillis();
while (System.currentTimeMillis() - startTimeMillis < timeLimitMillis) {
runIteration();
}
}
protected abstract void runIteration();
}
Then in your subclass override, runIteration() and perform a single "step" of the task.
The only reasonably reliable way to kill a task is to run it in a separate process and kill that process if it times out. Using any other approach with a library which does not support timeouts is likely to be error prone at best.
from my point of view I think that such stuff requires some more robust foundations than plain Java standard classes , that 's why I would suggest to use any scheduler infrastructure (Quartz or any other project) which may gives you handles (job identifiers) to kill your time consuming tasks .
You may have something like this :
Main Thread launches the Quartz Scheduler , receive subscriptions from different jobs
saying : Job1,Job 2 and TimeCheckerJob
TimeCheckerJob would be a forever job ,notified to any new job and would check for living time for each any new job... In this job you would have to deal with start time of each job, beware of the OS clocks and don't try to setup too hard constraints (nanoseconds is pure fiction).
HTH
My 2 cents
Jerome
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());