Am I doing something really stupid here? I am trying to execute a method every minute or so, forever, or until I stop the program.
while(true) {
this.doSomethingPeriodically();
Calendar now = Calendar.getInstance();
int minutes = now.get(Calendar.MINUTE);
int resume = minutes + 1;
while (now.get(Calendar.MINUTE) < resume) {
// waiting for a minute
}
}
This code will never leave the loop. It's an endless loop, since the Calendar instance refered to by now won't change.
Also, what you try to do here is implement busy waiting which is a very bad idea (it uses CPU time doing nothing interesting).
The correct way to sleep is to use Thread.sleep().
the simplest way for execute tasks repeteadly in java is the java.util.TimerTask and java.util.Timer api.
A simple code is:
public class PrinterTimerTask extends java.util.TimerTask {
#Override
public void run() {
System.out.println( 'Current time is: ' + System.nanoTime() );
}
public static void main(String[] args) {
long delay = 0;
long period = 60000;
java.util.Timer timer = new java.util.Timer(threadName);
PrinterTimerTask task = new PrinterTimerTask();
timer = new Timer("SomeThreadNameForProfiler");
timer.schedule( task, delay, period );
}
}
Variables:
task - task to be scheduled.
delay - delay in milliseconds before task is to be executed.
period - time in milliseconds between successive task executions.
More info:
Timer and TimerTask javadoc:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Timer.html
http://java.sun.com/j2se/1.5.0/docs/api/java/util/TimerTask.html
Another example:
http://www.javapractices.com/topic/TopicAction.do?Id=54
[]'s,
And Past
Try using the Timer class instead. It's meant for this sort of thing:
http://www.javapractices.com/topic/TopicAction.do?Id=54
https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html
Edit:
I just read that there's a newer replacement for Timer: ExecutorService. I've never used it, but it seems to have some advantages:
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ExecutorService.html
Java Timer vs ExecutorService?
Try using sleep instead, as it won't cause the processor to continue working on the thread:
Thread.sleep()
while(true) {
this.doSomethingPeriodically();
Thread.sleep(60000);
}
It would be better to use a Timer or at least use a sleep.
What you're trying to do here is called busy waiting. You are unnecessarily using huge amounts of CPU time (and you would even be using unnecessary memory if you fixed your bug and created a new Calendar instance in each loop).
What you actually want is the method Thread.sleep(), it is pretty well explained in a tutorial on sun.com.
It's better to use the sleep function: CurrentThread.sleep() and you specify the number of milliseconds that you want as a delay. It's better than busy waiting...
Related
Let's say I implemented a method which sleeps the current thread for 10 seconds. Now I want to write a unit test case to test the functionality of this method. How can I do this? Is the below code a better option?
#Test
public void testSleep() {
long start = System.currentTimeMillis();
invokeFunction(2000);
long end = System.currentTimeMillis();
Assert.assertTrue(end - start > 2000);
}
I would say the code you attached is a fine test to test that the duration of invokeFunction(2000) does indeed take at least 2000ms. Though, it doesn't prove that the function takes roughly the amount of time you spec.
#Test
public void testSleep() {
for(int i=250; i<3000; i+= 250) {
long start = System.currentTimeMillis();
invokeFunction(i);
long end = System.currentTimeMillis();
Assert.assertTrue(end - start >= i);
Assert.assertTrue(end - start <= i+ 250);
}
}
This way you can show that the function takes roughly the amount of time give to it, with a tolerance of 250ms. With your original test if the invokeFunction method was hardcoded to sleep for 5000ms then your test would pass, but the implementation would not actually be correct.
i would say it depends what you want to test. you are not testing that the function actually sleeps thread X seconds, you are testing that the method takes at least X seconds to complete.
I mean, if the function is doing more things than just Thread.sleep, you are counting all of the stuff.
Note that i say at least, since there is no guarantee that the thread will sleep this amount of time exactly; it may take more time to awake (jvm will do its best).
but TBH i don't know of any other better approach than what you are doing, without doing changes in your function implementation just for the sake of being able to test that (like having an intermediate component which only purpose is just to sleep the thread and just monitor enter and exit from that component).
I have a Java application that is used to communicate with an embedded device over a UART connection (RS422). The host queries the microcontroller for data in 5 millisecond intervals. Up until recently I've been using ScheduledExecutorService scheduleAtFixedRate to call my communication protocol method, but it turns out scheduleAtFixedRate is very unreliable for this desired level of precision (as many other posts reveal). Among the data returned from the microcontroller is a timestamp (in microseconds), allowing me to verify the interval between received data packets independently of the JVM. Needless to say, the interval when using scheduleAtFixedRate varied wildly - up to 30 milliseconds between packets. Additionally, the scheduler will then try to overcompensate for the missed cycles by calling the Runnable several times within one millisecond (again, no surprise to anyone here).
After some searching, there seemed to be a consensus that the JVM simply could not be trusted to ensure any kind of precise scheduling. However, I decided to do some experimenting on my own and came up with this:
Runnable commTask = () -> {
// volatile boolean controlled from the GUI
while(deviceConnection) {
// retrieve start time
startTime = System.nanoTime();
// time since commProtocol was last called
timeDiff = startTime - previousTime;
// if at least 5 milliseconds has passed
if(timeDiff >= 5000000) {
// handle communication
commProtocol();
// store the start time for comparison
previousTime = startTime;
}
}
};
// commTask is started as follows
service = Executors.newSingleThreadScheduledExecutor();
service.schedule(commTask, 0, TimeUnit.MILLISECONDS);
The result of this was fantastic. Adjacent timestamps never varied by more than 0.1 milliseconds from the expected 5 millisecond interval. Despite this, something about this technique doesn't seem right, but I haven't been able to come up with anything else that works. My question is basically whether or not this approach is OK, and if not, what should I do instead?
(I am running Windows 10 with JDK 8_74)
Based on the information I've received in the comments, I've decided to use leave my code essentially intact (with the exception of Thread.yield() which I've added to the while loop). I have used this for a few months now and am very satisfied with the performance from this approach. See the final code below.
Runnable commTask = () -> {
// volatile boolean controlled from the GUI
while(deviceConnection) {
// retrieve start time
startTime = System.nanoTime();
// time since commProtocol was last called
timeDiff = startTime - previousTime;
// if at least 5 milliseconds has passed
if(timeDiff >= 5000000) {
// handle communication
commProtocol();
// store the start time for comparison
previousTime = startTime;
}
Thread.yield();
}
};
// commTask is started as follows
service = Executors.newSingleThreadScheduledExecutor();
service.execute(commTask);
I'm doing some tasks using Java. I have some problems with timing: I need to set up a timer with a fixed period of repetition. I tried both, the standard Timer, and TimerTask and the ScheduledExecutor, but both work in an approximate manner, i.e. if I set an interval of 40 milliseconds, using the following code (for Executors)
m_executor = Executors.newScheduledThreadPool(5);
Runnable thread = new TheThread();
m_executor.scheduleWithFixedDelay(thread, 0, 40000000, TimeUnit.NANOSECONDS);
And then I try to print "time" of each execution
private static final class TheThread implements Runnable {
#Override
public void run() {
System.out.println(System.nanoTime()/1000000);
}
}
The result is something like this:
xxxxxx300
xxxxxx345
xxxxxx386
xxxxxx428
...
As you can see, if I correctly understand nanoTime() the function is called at a random intervals, close to that I specified (40 milliseconds), but not exactly what I specified!
When I worked with C and Win32s, for example, I was able to use the CreateTimerQueueTimer() function that is highly accurate, and the callback function was called every 40 milliseconds:
xxxxxx300
xxxxxx340
xxxxxx380
...
I tried to move time measurement to avoid the printing time. I also tried to use scheduleAtFixedRate(), but unfortunately the period varies between 35 and 47 ms (set to 40 in the method).
I'm wondering how people can make software such emulators or similar things, that requires a precise period observance...:-)
I thought of a possible solution that I would like to show you and ask to you, experts:) how this idea could be applicable (and safe)
The problem here is to run some methods every X milliseconds, say 40 ms. The question here is about Java timer/timing, but what about this simple solution?
public class MyEmulator extends Thread {
private long start = 0;
private long end = 0;
#Override
public void run() {
long exec_time;
start = System.nanoTime();
/*
* Do the emulator-loop
*/
end = System.nanoTime();
exe_time = (end - start)/1000000;
// wait with a whil() (40 - exec_time)
}
}
With this solution, when I print the elapsed time after the waiting whilt() is ended the result is exactly 40 ms (without decimal, that is not quit important).
Do you think it would be safe, i.e. are really 40 ms?
I don't think you're going to be able to manage this in Java with this level of precision. Unlike your C/Win32 solutions, your Java solution is running in a JVM with multiple threads (of varying priority) and with garbage collection running and taking resources.
Having said that, I would experiment with the scheduleAtFixedRate() method, which executes at a regular period. scheduleWithFixedDelay() will execute and upon completion delay for a fixed amount of time. Hence not accounting for the time taken for your method to actually run.
I have written the following Java code:
Calendar now = Calendar.getInstance();
now.setTime(new Date());
Date currentDate = null;
while (now.compareTo(stop) < 0 ) {
currentDate = new Date();
now.setTime(currentDate);
}
that is meant to track down the time passing while other components (in particular: a Twitter Streaming listener) perform other actions. So, this is not meant to be a simple sleep, since other components are running in the meanwhile: this loop is just meant to keep the machine occupied for a while, until the date indicated by stop arrives.
However, by doing this the memory size keeps increasing a lot. I profiled the thing and I saw that this generates a huge amount of Date objects in memory.
Is there a smarter way of doing this?
Thank you in advance.
The minimum change is to use setTimeInMillis using System.currentTimeMillis rather than setTime:
while (now.compareTo(stop) < 0 ) { // Ugh, busy wait, see below
now.setTimeInMillis(System.currentTimeMillis());
}
...or actually, just use milliseconds in the first place:
long stopAt = stop.getTimeMillis();
while (System.currentTimeMillis() < stopAt) { // Ugh, busy wait, see below
}
However, surely with broader context there's a way to avoid busy-waiting at all. Busy-waits are almost never appropriate.
So, this is not meant to be a simple sleep, since other components are running in the meanwhile: this loop is just meant to keep the machine occupied for a while, until the date indicated by stop arrives.
Presumably those components are running on other threads, as your while loop is a busy-wait.
That being the case, this thread should sleep — either for a period of time, or until it's woken up by something else.
For instance, you haven't said what stop is, but as you're using it with compareTo presumably it's a Calendar. So it should be possible to get the difference (in milliseconds, via getTimeInMillis) between stop and now, and sleep rather than busy-waiting:
Calendar now = Calendar.getInstance(); // Initializes to "now", no need to do that yourself
long delay = stop.getTimeInMillis() - now.getTimeInMillis();
if (delay > 0) {
Thread.sleep(delay);
}
As the title, is there a way to get the Timer working under the threshold of a millisecond?
My question is similar the following one, but it is intended for Java:
Thread.Sleep for less than 1 millisecond
If you want to sleep, Thread.sleep has 2 methods, one of which accepts nanoseconds. If you want to schedule a task, you can use a ScheduledExecutorService which schedule methods can use nanoseconds too.
As explained by #MarkoTopolnik, the result will most likely not be precise to the nanosecond.
Thread.sleep(long millis, int nanos)
Also check out this answer with details on issues with this on Windows.
You could wait on an object that nobody will notify...
synchronized (someObjectNobodyWillNotify) {
try {
someObjectNobodyWillNotify.wait(0, nanosToSleep);
}
catch (InterruptedException e) {
Thread.interrupt();
}
}
(In this scenario, I'm guessing spurious wakeups are okay. If not, you need to record your System.nanoTime() at the start and wrap the wait in a loop that checks that enough time has elapsed.)
The java.util.concurrent package uses TimeUnit for timing. TimeUnit has a NANOSECONDS field.