How do you activate or run a loop every tenth of a second? I want to run some script after an amount of time has passed.
Run a script every second or something like that. (notice the bolded font on every)
You can use a TimerTask. e.g.
timer = new Timer();
timer.schedule(new RemindTask(), seconds*1000);
You simply need to define a Runnable. You don't have to worry about defining/scheduling threads etc. See the Timer Javadoc for more info/options (and Quartz if you want much more complexity and flexibility)
Since Java 1.5:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(new RepeatedTask(), 0, 100, TimeUnit.MILLISECONDS);
and
private class RepeatedTask implements Runnable {
#Override
public void run() {
// do something here
}
}
(remember to shotdown() your executor when finished)
You sleep.
Check out Thread.sleep() but be warned that you probably really don't want your whole program to sleep, so you might wish to create a thread to explicitly contain the loop and it's sleeping behavior.
Note that sleep only delays for a number of milliseconds; and, that number is not a perfect guarantee. If you need better time resolution you will have to use System.currentTimeMillis() and do the "time math" yourself. The most typical scenario is when you run something and you want it to run ever minute. The time the script runs must be captured by grabbing System.currentTimeMillis() before and after the script, and then you would need to sleep the remaining 1000 - scriptRunTime milliseconds.
Related
The articles on the site related to Timer talk about how to use Timer to program.
I ask a different question.
How does Java perform Timer method?
Since it is said to avoid time-consuming work by not to use while loop to check whether the current time is the required time point, I think Timer is not implemented simply by using while loop to continuously checking and comparing the current time to the desired time point.
Thank you!
I think Timer is not implemented simply by using while loop to continuously
checking and comparing the current time to the desired time point.
YES, IT IS. The only optimization is; it is using priority queue based on nextExecutionTime for tasks.
JavaDoc states
Timer object is a single background thread that is used to
execute all of the timer's tasks, sequentially. Timer tasks should
complete quickly. If a timer task takes excessive time to complete,
it "hogs" the timer's task execution thread. This can, in turn, delay
the execution of subsequent tasks
Timer class contains
TaskQueue which is a priority queue of TimerTasks, ordered on nextExecutionTime.
TimerThread(queue) the timer's task execution thread, which waits (queue.wait()) for tasks on the timer queue.
TimerThread has private void mainLoop() { where continuous while(true) will keep checking the tasks by comparing nextExecutionTime with currentTimeMillis
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired = (executionTime<=currentTime)) {
and if it reaches then calling
if (taskFired) // Task fired; run it, holding no locks
task.run();
According for the javadoc
This class does not offer real-time guarantees: it schedules tasks
using the Object.wait(long) method.
If you look in the code you will find a method called main loop. The first couple of lines are copied below.
private void mainLoop() {
while (true) {
try {
And... it uses a while loop inside of it along with Object.wait() to do the waiting.
Sometimes the duration of a repeated task is longer than its period (In my case, this can happen for hours at a time). Think of a repeated task that takes 7 minutes to run and is scheduled to run every 10 minutes, but sometimes takes 15 minutes for each run for a few hours in a row.
The Timer and ScheduledThreadPoolExecutor classes both have a scheduleAtFixedRate method that is usually used for this type of functionality. However, both have the characteristic that they 'try to catch up when they fall behind'. In other words, if a Timer falls behind by a few executions, it builds up a queue of work that will be worked on continuously until it catches back up to the number of runs that would have happened if none of the tasks had taken longer than the specified period. I want to avoid this behavior by skipping the current execution if the previous run is not complete.
I have one solution that involves messing around with the afterExecution method of a pooled executor, recalculating a delay, and rescheduling the runnable with the new delay, but was wondering if there's a simpler way, or if this functionality already exists in a common library somewhere. I know about scheduling with a fixed delay rather than a fixed period, but this will not work for me since it's important to try to execute the tasks at their fixed times. Are there any simpler options than my afterExecution solution?
I think what you want is for the long-running task itself to not run in the ScheduledExecutorService itself, but in a background thread. Then the fixed-rate task will always complete quickly, since it is only used for checking whether to start the actual task in the background (or not, if it's still running from last time).
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
final Runnable actualTask = null;
executorService.scheduleAtFixedRate(new Runnable() {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private Future<?> lastExecution;
#Override
public void run() {
if (lastExecution != null && !lastExecution.isDone()) {
return;
}
lastExecution = executor.submit(actualTask);
}
}, 10, 10, TimeUnit.MINUTES);
You could use scheduleWithFixedDelay method instead. It's similar but this one does not have a queue for missed runs and instead starts counting again only when the current Runnable was terminated.
The documentation states the reexecution of the Runnable will be scheduled based on the delay parameter:
The delay between the termination of one execution and the commencement of the next.
Make a third class, say called Coordinator. Coordinator has a synchronized startRunning() method which sets isRunning to true and returns true if another thread was not running already. There should also be a synchronized stopRunning method which sets isRunning to false. It returns true if a runnable is already running. You make a single instance of this class and pass a reference to all of the runnables you construct. In the runnable's run method you first call startRunning and check the return to verify that another one isn't running already. Make sure to put the code in run() in a try-finally and call stopRunning from within the finally block.
There are n object which perform some actions. After performing an action a timestamp will be updated. Now I want to implement a timeout-thread which verifies if a timestamp is older than for example 60 seconds.
My first solution was to do that with a thread (while-loop + sleep) which is holding a list with all objects including the last timestamp. Now I have the problem that there is a worst-case scenario where the thread needs 59 seconds plus sleep time to decide for a timeout.
I’m searching for a solution like a Timer where it is possible to update the delay time.
Any ideas?
I think using a monitor object with wait/notify is reasonable (you may use Condition with await/signal if you are using JDK >= 5)
idea is simple:
Worker thread:
doYourActualWork();
synchronized(jobFinishedMonitor) {
updateTimestamp();
jobFinishedMonitor.notify();
}
Timeout thread:
synchronized(jobFinishedMonitor) {
while(within60Second(timestamp)) {
jobFinishedMonitor.wait(60);
}
if (within60Second(timestamp)) {
timeoutHappened=true;
}
}
if (timeoutHappened) {
// do timeout handling
}
For the question, it's not clear what you want to do with the timeout. Here I present you two options to implement a lightweight timeout: monitored vs controlled.
Monitored Timeout
For a global timer, you can use the Timer facility from the JDK:
public TimeoutTask implements TimerTask {
List<MonitorableObject> objects;
public TimeoutTask(List<MonitorableObject> objects) {
// make sure you can share this collection concurrently,
// e.g. copyonwritearraylist
this.objects = objects;
}
public void run() {
// objects -> filter(isTimeOut(currentTime)) -> do something
}
}
Timer timer = new Timer();
timer.schedule(new TimeoutTask(myObjectList), 0,60*1000); // repeat each 60secs
There's a similar construction possible using a ScheduledExecutorService:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
// Note that I can use here TimeoutTask b/c TimerTask is a Runnable -
// this is just for the example. You'd better implement a plain runnable.
scheduler.schedule(new TimeoutTask(myObjectList), 60, TimeUnit.SECONDS);
I prefer the ScheduledExecutorService above the Timer facility, as the SchedulerExecutor can hold a pool of threads. Also, the underlying threadpool can be used for other operations invoking scheduledExecutorService.execute(...) for immediate concurrent execution (not scheduled), making it a generic executor facility, rather than a dedicated timer function.
In both cases, you'll need to take special care to safely get the timeout value from your the objects you are monitoring. Typically, you will use a synchronized method in the object to ask for it's timeout status.
Enforced Timeout
The ExecutorService provides you with an API to execute a set of tasks within a given timeout. e.g.
List<Callable<?>> myTasks = ...;
// populate myTasks with Callable`s that wrap your intended execution
ExecutorService executorService = ... ;
List<Future<?>> results = executorService.invokeAll(myTasks, 60, TimeUnit.SECONDS);
After this method returns, you can ask every Future whether it succeeded within the time given.
Interrupt the thread every time you update a timestamp. Then it will loop, find nothing to do, sleep, and if nothing else has happened to the timestamp, expire it. If it gets interrupted a second time, so much the better. And at all times it should never sleep for longer than 60 minus (current time minus the oldest timestamp).
I am having trouble with the following bit of code.
//Send Creation email
ListServDAO.sendCreateEmail(orgId, full, request.getSession().getServletContext());
//Force a 1 minute pause
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
//Send add members email
ListServDAO.sendAddMembersEmail(orgId, request.getSession().getServletContext());
}
}, 0, 60 * 1000);
The sendAddMembersEmail function does not wait 1 minute to send after the sendCreateEmail function call. I am not sure why it is not waiting even after reading the java API. I do not wish to use the Thread.sleep method because I want the user to be able to use the application while waiting for the emails to send.
are you intending to repeatedly send emails? if not, why are you using the method which takes 2 longs (i.e. "repeatedly run this task every <period> milliseconds")? use the schedule(task, delay) method (and use a non-zero delay).
2nd parameter is the initial delay which you are passing as 0 hence it it executing it right then and there, pass 60000 second for it to wait for a minute and then send.
Since you just want it to send only once use, call Timer.schedule(TimerTask task, long delay)
Off-topic:
You should consider using ScheduledExecutorService instead of Timer. See Oracle Tutorial.
You have an extra zero.
What you are calling is Delayed with a Fixed-Delay Repeat Execution and what you want is a Single Delay Non Repeat execution.
You have the order of the params wrong:
schedule(TimerTask task, long delay, long period)
Schedules the specified task for repeated fixed-delay execution, beginning after the specified delay.
Swap the 0 and 60*1000.
I am working on a Java program and using Timer objects to run tasks every few minutes or hours. This works fine in normal operations, but I am running into a problem with "Sleep mode" on Mac (maybe on other OSes, but I haven't tried yet).
Consider this code sample:
//Setup the timer to fire the ping worker (every 3 minutes)
_PingTimer.scheduleAtFixedRate(new TimerTask(){
public void run(){
Program.PingThread = new PingWorker(Settings.Username, Settings.UserHash, true, true);
Program.PingThread.CheckOpenPort = true;
Program.SwingExecutor.execute(Program.PingThread);
}
}, 0, 180000);
In normal operation this would fire every 3 minutes with enough accuracy (I'm not concerned about the exact second or anything). The problem with this is after sleeping the computer for a few hours or so it seems to just BLAST the system with backlogged timer requests.
It seems to be running all of the missed timer hits during sleep at once trying to make up for lost time.
Is there a way i can prevent this? I tried using synchronized and some other thread techniques, but this only ensures that they aren't all running at the same time. They still continue to run one after another until the backlog is passed.
Thanks for any help you can provide!
Have you looked at the API? It clearly states the following:
In fixed-rate execution, each
execution is scheduled relative to the
scheduled execution time of the
initial execution. If an execution is
delayed for any reason (such as
garbage collection or other background
activity), two or more executions will
occur in rapid succession to "catch
up." In the long run, the frequency of
execution will be exactly the
reciprocal of the specified period
(assuming the system clock underlying
Object.wait(long) is accurate).
This is one reason why you should consider using a ScheduledExecutorService. This link may also prove useful.
Use schedule instead of scheduleAtFixedRate.