Whenever I use Thread.sleep(); in a do while loop, the hints tell me, "Invoking Thread.sleep in loop can cause performance problems." I have heard this from many other websites and books. What is something I can use instead?
Here's the code:
import javax.swing.*;
public class Delay {
public static void main(String[] args) throws Exception {
int difficulty;
difficulty = Integer.parseInt(JOptionPane
.showInputDialog("How good are you?\n" + "1 = evil genius...\n"
+ "10 = evil, but not a genius"));
boolean cont;
do {
cont = false;
System.out.println("12");
Thread.sleep(500);
String again = JOptionPane.showInputDialog("Play Again?");
if (again.equals("yes"))
cont = true;
} while (cont);
}
}
Try java.util.Timer and/or javax.swing.Timer. Play with them a bit, set initial delay, repetition period, etc. See what suits your needs.
Be sure to check differences between these two timers, for starters take a look at this question: Why are there two Timer classes in Java(one under javax.swing, one under java.util )?
Then try ScheduledExecutorService, as already suggested by #BoristheSpider.
Using Thread.sleep to do polling or similar update mechanism is ok approach. It's reasonable for instance if you want to repaint a canvas every 5 milliseconds, then you would use sleep(5). You could also use a hardware timer which will be more exact and relieve the CPU, but the usual approach is exactly Thread.sleep.
Related
I have a requirement for a class method to be called every 50 milliseconds. I don't use Thread.sleep because it's very important that it happens as precisely as possible to the milli, whereas sleep only guarantees a minimum time. The basic set up is this:
public class ClassA{
public void setup(){
ScheduledExecutorService se = Executors.newScheduledThreadPool(20);
se.scheduleAtFixedRate(this::onCall, 2000, 50, TimeUnit.MILLISECONDS);
}
protected void onCall(Event event) {
// do something
}
}
Now this by and large works fine. I have put System.out.println(System.nanoTime) in onCall to check its being called as precisely as I hope it is. I have found that there is a drift of 1-5 milliseconds over the course of 100s of calls, which corrects itself now and again.
A 5 ms drift unfortunately is pretty hefty for me. 1 milli drift is ok but at 5ms it messes up the calculation I'm doing in onCall because of states of other objects. It would be almost OK if I could get the scheduler to auto-correct such that if it's 5ms late on one call, the next one would happen in 45ms instead of 50.
My question is: Is there a more precise way to achieve this in Java? The only solution I can think of at the moment is to call a check method every 1ms and check the time to see if its at the 50ms mark. But then I'd need to maintain some logic if, on the off-chance, the precise 50ms interval is missed (49,51).
Thanks
Can I achieve a guaranteed sleep time on a thread?
Sorry, but No.
There is no way to get reliable, precise delay timing in a Java SE JVM. You need to use a Real time Java implementation running on a real time operating system.
Here are a couple of reasons why Java SE on a normal OS cannot do this.
At certain points, the GC in a Java SE JVM needs to "stop the world". While this is happening, no user thread can run. If your timer goes off in a "stop the world" pause, it can't be scheduled until the pause is over.
Scheduling of threads in a JVM is actually done by the host operating system. If the system is busy, the host OS may decide not to schedule the JVM's threads when your application needs this to happen.
The java.util.Timer.scheduleAtFixedRate approach is probably as good as you will get on Java SE. It should address long-term drift, but you can't get rid of the "jitter". And that jitter could easily be hundreds of milliseconds ... or even seconds.
Spinlocks won't help if the system is busy and the OS is preempting or not scheduling your threads. (And spinlocking in user code is wasteful ...)
According to the comment, the primary goal is not to concurrently execute multiple tasks at this precise interval. Instead, the goal is to execute a single task at this interval as precisely as possible.
Unfortunately, neither the ScheduledExecutorService nor any manual constructs involving Thread#sleep or LockSupport#parkNanos are very precise in that sense. And as pointed out in the other answers: There may always be influencing factors that are beyond your control - namely, details of the JVM implementation, garbage collection, JIT runs etc.
Nevertheless, a comparatively simple approach to achieve a high precision here is busy waiting. (This was already mentioned in an answer that is now deleted). But of course, this has several caveats. Most importantly, it will burn processing resources of one CPU. (And on a single-CPU-system, this may be particularly bad).
But in order to show that it may be far more precise than other waiting approaches, here is a simple comparison of the ScheduledExecutorService approach and the busy waiting:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class PreciseSchedulingTest
{
public static void main(String[] args)
{
long periodMs = 50;
PreciseSchedulingA a = new PreciseSchedulingA();
a.setup(periodMs);
PreciseSchedulingB b = new PreciseSchedulingB();
b.setup(periodMs);
}
}
class CallTracker implements Runnable
{
String name;
long expectedPeriodMs;
long baseTimeNs;
long callTimesNs[];
int numCalls;
int currentCall;
CallTracker(String name, long expectedPeriodMs)
{
this.name = name;
this.expectedPeriodMs = expectedPeriodMs;
this.baseTimeNs = System.nanoTime();
this.numCalls = 50;
this.callTimesNs = new long[numCalls];
}
#Override
public void run()
{
callTimesNs[currentCall] = System.nanoTime();
currentCall++;
if (currentCall == numCalls)
{
currentCall = 0;
double maxErrorMs = 0;
for (int i = 1; i < numCalls; i++)
{
long ns = callTimesNs[i] - callTimesNs[i - 1];
double ms = ns * 1e-6;
double errorMs = ms - expectedPeriodMs;
if (Math.abs(errorMs) > Math.abs(maxErrorMs))
{
maxErrorMs = errorMs;
}
//System.out.println(errorMs);
}
System.out.println(name + ", maxErrorMs : " + maxErrorMs);
}
}
}
class PreciseSchedulingA
{
public void setup(long periodMs)
{
CallTracker callTracker = new CallTracker("A", periodMs);
ScheduledExecutorService se = Executors.newScheduledThreadPool(20);
se.scheduleAtFixedRate(callTracker, periodMs,
periodMs, TimeUnit.MILLISECONDS);
}
}
class PreciseSchedulingB
{
public void setup(long periodMs)
{
CallTracker callTracker = new CallTracker("B", periodMs);
Thread thread = new Thread(new Runnable()
{
#Override
public void run()
{
while (true)
{
long periodNs = periodMs * 1000 * 1000;
long endNs = System.nanoTime() + periodNs;
while (System.nanoTime() < endNs)
{
// Busy waiting...
}
callTracker.run();
}
}
});
thread.setDaemon(true);
thread.start();
}
}
Again, this should be taken with a grain of salt, but the results on My MachineĀ® are as follows:
A, maxErrorMs : 1.7585339999999974
B, maxErrorMs : 0.06753599999999693
A, maxErrorMs : 1.7669149999999973
B, maxErrorMs : 0.007193999999998368
A, maxErrorMs : 1.7775299999999987
B, maxErrorMs : 0.012780999999996823
showing that the error for the waiting times is in the range of few microseconds.
In order to apply such an approach in practice, a more sophisticated infrastructure would be necessary. E.g. the bookkeeping that is necessary to compensate for waiting times that have been too high. (I think they can't be too low). Also, all this still does not guarantee a precisely timed execution. But it may be an option to consider, at least.
If you really have hard time constraints, you want to use a real-time operating system. General computing does not have hard time constraints; if your OS goes to virtual memory in one of your intervals, then you can miss your sleep interval. The real-time OS will make the tradeoff that you may get less done, but that work will can be better scheduled.
If you need to do this on a normal OS, you can spinlock instead of sleeping. This is really inefficient, but if you really have hard time constraints, it's the best way to approximate that.
That will be hard - think about GC... What I would do is to grab time with nanoTime, and use it in calculations. Or in other words I would get exact time and use it in calculations.
Yes (assuming you only want to prevent long term drifts and don't worry about each delay individually). java.util.Timer.scheduleAtFixedRate:
...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). ...
Basically, do something like this:
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
this.onCall();
}
}, 2000, 50);
while(!isRunning){
now = getSystemTime();
deltaTime = now - lastTime;
lastTime = now;
if(deltaTime >= 1000){
//do something
}
}
This piece of code looks awkward to me. I want the thread to "do something" every 1000 units of time, but the while loop will run infinitely before 1000 units of time passes, which wastes resoure of CPU. How do you think I could refactor this piece of pseudo code? Notice that it may be true that "do something" may take more than 1000 units of time.
PS:
I am coding using java and want a solution to the problem with Java.
Take a look at Java scheduled executors. There is a method called scheduleAtFixedRate you can use. There is a class called TimeUnit which is used in this method to make things run at certain periods. Disadvantage to this is you have to create a instanve of Callable or Runnable which is a bit clunky in my opinion
First, I would make a function just to keep track of time so the code looks cleaner. Second, if you put a sleep inside the while so we dont occupy CPU time with busy wait. You can have more timed sections with more timer variables.
int countTime(int & time){
now = getSystemTime();
deltaTime = now - time;
lastTime = now;
return deltaTime
}
...
while(!isRunning){
if(countTime(timer) >= 1000){
//do something
}
usleep(100000) // sleep so we don't occupy CPU
}
The problem here is that the code is performing a busy wait, meaning, wasting CPU cycles until delta is bigger than 1 second.
It would be better to simply sleep for a second instead, and allow other processes to take advantage of the CPU cycles while your process is doing nothing:
while(!isRunning){
doSomething();
sleep(1000); // see implementation below
}
...
void sleep(int milli) {
try {
Thread.sleep(milli);
} catch (InterruptedException e) {
// ignore
}
}
Is it going to run forever? What is the context?
Try to make it like this:
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable beeper = new Runnable() {
public void run() { algorithm something here! }
};
final ScheduledFuture<?> beeperHandle =
scheduler.scheduleAtFixedRate(beeper, 1000, 1000, TimeUnit.MILLISECONDS);
Maybe it solve your problem!
If you have some question about the methods posted above, please check the oracle documentation:
https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledExecutorService.html
Pls help me to understand how can we make a thread to sleep for a infinite time period .
I can't think of a good reason for doing this. As one of the comments noted Long.MAX_VALUE is roughly 292 billion years so probably Thread.sleep(Long.MAX_VALUE) is enough. But if you want a theoretical infinite sleep solution:
while (true) {
Thread.sleep(Long.MAX_VALUE);
}
Literally, you can't. No Java application can run for an infinite amount of time. The hardware will die first :-)
But in practice1, the following will sleep until the JVM terminates ... or the thread is interrupted.
public void freeze() throws InterruptedException {
Object obj = new Object();
synchronized (obj) {
obj.wait();
}
}
If you wanted to you could catch the exception within a while (true) loop. And doing the same with "sleep(max int)" is equivalent.
But frankly, making a thread go to sleep "for ever" is wasteful2, and probably a bad idea. I have no doubt that there will be better ways to achieve what you are really trying to do.
1 - These solutions I talk about are for when a thread needs to make itself go to sleep. If you one thread to unilaterally make a different thread go to sleep, it can't do that safely. You could use the deprecated Thread.suspend() method, but it is dangerous, and it may not be available on future Java platforms.
2 - A thread stack occupies a significant amount of memory, and it cannot be released until the thread terminates.
Thread.currentThread().join();
Will sleep until the JVM is killed.
Make it wait for a mutex or resource that will never be released. It's the deadlock principle. The better way is to make the thread to finish his code, so it will end and not be started again.
Edit:
I don't recommand an infinite loop since it's the pooling principle. It will consume a lot of resources for nothing.
You can use class CyclicBarrier from the JDK.
new CyclicBarrier(2).await();
Constructor argument is the number of threads that must invoke await method before the barrier is reached.
It's actually quite easy if you do it this way:
public static boolean timerController = false;
Timer timer = new Timer();
public TimerTask task = new TimerTask() {
public void run() {
if(timerController == false){
tracker();
t.setText("<html><br/>Day " + day + ", hour " + hour + "<br/>");
System.out.println("Hour: " + hour + " Day: " + day + " Real time seconds " + realTime + " Seconds");}
}
};
public void start() {
timer.scheduleAtFixedRate(task, 1000, 1000);
}
public void pause(){
timerController = true;
}
public void resume(){
timerController = false;
}
Make a timer object in another class, and simply start, pause, and resume with the three methods. It should "stop" when you pause the timer, and you won't need to deal with any exception handling or any try/catch statements!
I want to have a thread that loops at a constant amount of times per second for example a render loop that aims for a constant framerate. The loop would obviously slow if the time it takes exceeds the time allowed.
Thanks.
How about
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ses.scheduleAtFixedRate(0, delay, TimeUnit.MILLI_SECONDS, new Runnable() {
public void run() {
// do something
}
});
or
long delay = ....
long next = System.currentTimeMillis();
while(running) {
// do something
next += delay;
long sleep = next - System.currentTimeMillis();
if (sleep > 0)
Thread.sleep(sleep);
}
There are two basic techniques you need two consider:
seperate updateing your model or state of the world from rendering it.
If you have done that, you can sleep/wait the appropriate amount of time before rendering stuff or skip the rendering for some frames if you fall behind your planed schedule.
I can recommend two good tututorials on how to implement something like a game loop in java/android.
First one about the basics is http://obviam.net/index.php/a-very-basic-the-game-loop-for-android/
and the second one has a focus on constant Frames per Second: http://obviam.net/index.php/the-android-game-loop/. I think the lessons apply to regualar java as well.
Im trying to get a timer to work in my current java project that adds 1 to an integer variable every n microseconds (e.g. 500 for 1/2 a second), within an infinite loop, so that it is always running while the program runs.
Heres the code i have currently:
public class Ticker
{
public int time = 0;
long t0, t1;
public void tick(int[] args)
{
for (int i = 2; i < 1; i++)
{
t0 = System.currentTimeMillis();
do
{
t1 = System.currentTimeMillis();
}
while (t1 - t0 < 500);
time = time + 1;
}
}
}
Everyone was so helpful with my last question, hopefully this one is just as easy
Here is an comparable ScheduledExecutorService example which will update the time variable with a 500 millisecond interval:
ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
exec.scheduleAtFixedRate(new Runnable(){
private int time = 0;
#Override
public void run(){
time++;
System.out.println("Time: " + time);
}
}, 0, 500, TimeUnit.MILLISECONDS);
This approach is preferred over using Timer.
I think you want
Thread.sleep(500);
At the moment you're consuming CPU cycles waiting for 500ms (you mention microseconds but I believe you want milliseconds). The above puts your current thread to sleep for 500ms and your process won't consume any CPU (or minimal at least - garbage collection will still be running). If you watch the CPU when you run your version you should see the difference.
See here for more info.
If you need to do it in a different thread, take a look on Timer:
int delay = 500; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
time++
}
};
new Timer(delay, taskPerformer).start();
Note that the code above cannot utilize a local variable (they must be declared as final to access them in an anonymous class). It can be a member however.
What you have is rather inefficient, since it wastes CPU cycles waiting for the next wakeup time. If I were you, I'd rewrite the function using Thread.sleep().
As to why your current code doesn't work, your for loop conditions are off, so the loop is never entered.
To have the timer code run concurrently with whatever other logic you have in your program, you'll need to look into threading.
It sounds like you might want to look into multithreading. If you search SO for this, you will find several good question/answer threads. There are also tutorials elsewhere on the web...
Have a look at Timer or better ScheduledExecutorService. They enable you to execute some action periodically and handle the computations surrounding that.