I am creating a program that makes a calculation every minute. I don't know exactly how to do this efficiently, but this is some pseudo code I have written so far:
stockCalcTimerH = System.currentTimeMillis() - 1;
stockCalcTimerI = stockCalcTimerH;
stockCalcTimer = System.currentTimeMillis();
if (stockCalcTimerI < stockCalcTimer) {
*do calcuations*
stockCalcTimerI + 60000;
When I print both values out on the screen, it comes out as this:
stockCalcTimerI = 1395951070595
stockCalcTimer = 1395951010596
It only subtracts the number, and doesn't add the 60000 milliseconds...
I'm kind of new to Java, but any feedback helps.
Thanks for reading!!
stockCalcTimerI + 60000;
The new value never gets assigned to a variable.
Change that to:
stockCalcTimerI += 60000;
Which is the same as
stockCalcTimerI = stockCalcTimerI + 60000;
You can use java.util.Timer class to schedule runs.
TimerTask task = new TimerTask() {
#Override public void run() {
// do calculations
}
};
int delay = 0; // no delay, execute immediately
int interval = 60*1000; // every minute
new Timer().scheduleAtFixedRate(task, delay, interval);
Related
Okay so I am trying to add methods this stopwatch class to pause and resume the time on the stopwatch. The stopwatch works fine and so does the resume method. The problem is with the pause method.
When I use elapsedTime to check how much time has passed and then the pause method to pause the time and then I wait for a little bit and check the time again, the time paused. However if I then wait for a little bit and check the time again by using elapsedTime (without using pause() again) the time changes as if I had resume the time. If I check time, pause, check time, pause,... then the time does not change but obviously I want the time to stay paused until I resume.
public class Stopwatch {
private final long start;
private long additionalTime;
private long pauseStart;
public Stopwatch() {
start = System.currentTimeMillis();}
public void pause() {
if (pauseStart == 0)
pauseStart = System.currentTimeMillis();
}
public void resume() {
if (pauseStart != 0) {
long stopTime = System.currentTimeMillis() - pauseStart;
additionalTime += stopTime;
pauseStart = 0;
}
}
public double elapsedTime() {
long now = System.currentTimeMillis();
if (pauseStart != 0) {
long stopTime = System.currentTimeMillis() - pauseStart;
additionalTime += stopTime;
pauseStart = 0;
}
return ((now - start) - additionalTime) / 1000.0;}
public static void main(String[] args) {
Stopwatch watch = new Stopwatch();
double total = 0.0;
for (int i = 0; i < 100000000; i++)
total += Math.random();
double time = watch.elapsedTime();
StdOut.println(timi);
watch.pause();
for (int i = 0; i < 200000000; i++)
total += Math.random();
time = watch.elapsedTime();
StdOut.println(time);
for (int i = 0; i < 200000000; i++)
total += Math.random();
time = watch.elapsedTime();
StdOut.println(time);
}
}
I think you should use two different classes. Have you considered something like this?
Rename your Stopwatch class to, let's say: InnerStopwatch.
Create a new Stopwatch class that holds a List of InnerStopwatchs.
When you start a Stopwatch, it creates a new InnerStopwatch, starts it and stores a reference to it as your "current inner stopwatch"
When you pause the Stopwatch, it calls the stop method on the "current inner stopwatch".
When you resume the Stopwatch, it creates a new InnerStopwatch and starts it; and marks it as the new "current inner stopwatch"
When you ask for the elapsed time, than it sums the elapsed times of all inner stopwatchs in the List.
Please let me know if that works for you.
I would like to write a test for a method, that calls observers in a specific intervall, so that they will execute a method. The timer-object runs in its own thread.
Method of timer to be tested
private long waitTime;
public Metronome(int bpm) {
this.bpm = bpm;
this.waitTime = calculateWaitTime();
this.running = false;
}
public void run() {
long startTime = 0, estimatedTime = 0, threadSleepTime = 0;
running = true;
while (running) {
startTime = System.nanoTime();
tick();// notify observers here
estimatedTime = System.nanoTime() - startTime;
threadSleepTime = waitTime -estimatedTime;
threadSleepTime = threadSleepTime < 0 ? 0 : threadSleepTime;
try {
Thread.sleep(threadSleepTime / 1000000l);
} catch (InterruptedException e) {
// sth went wrong
}
}
}
Snippet from my testclass
private int ticks;
private long startTime;
private long stopTime;
#Test
public void tickTest(){
metronome.setBpm(600);
startTime = System.nanoTime();
metronome.run();
long duration = stopTime - startTime;
long lowThreshold = 800000000;
long highThreshold = 900000000;
System.out.println(duration);
assertTrue(lowThreshold < duration);
assertTrue(duration <= highThreshold);
}
#Override
public void update(Observable o, Object arg) {
ticks ++;
if(ticks == 10){
metronome.stop();
stopTime = System.nanoTime();
}
}
Right now, my testclass registers as an observer at the object in question, so that i can count the number of times tick() was executed. The test measures the time before and after the execution, but it feels awkward to me, to test the behaviour this way.
Any suggestions for improving the test?
Sometimes the solution is to use something from a standard library that is sufficiently simple such that it does not need to be tested. I think SchedulerExecuterService will do the trick for replacing the home made Timer being tested here. Note that it is pretty rare to be bit by a bug in library code, but they do exist.
In general though, I think it is okay to create a helper class or use a mocking framework (Mockito) to do something simple like counting "ticks".
P.S. You can replace Thread.sleep(threadSleepTime / 1000000l) with TimeUnit.NANOSECONDS.sleep(threadSleepTime) ... which moves some logic from your code into the standard library.
Based on your comments I changed my code. Instead of implementing the Observer-interface in my testclass, I now created a private class, that implements the interface an registers at my timer.
Thanks for your time and thoughts.
Here is what the code now looks like:
revised testcode
#Test(timeout = 2000)
public void tickTest(){
long lowThreshold = 400000000;
long highThreshold = 600000000;
TickCounter counter = new TickCounter();
metronome.addObserver(counter);
metronome.setBpm(600);
startTime = System.nanoTime();
metronome.run();
long duration = System.nanoTime() - startTime;
assertTrue(lowThreshold <= duration);
assertTrue(duration <= highThreshold);
}
private class TickCounter implements Observer{
private int ticks;
public TickCounter(){
ticks = 0;
}
#Override
public void update(Observable o, Object arg) {
ticks++;
if(ticks == 5){
metronome.stop();
}
}
}
snippet from my revised timer
private long expectedTime; // calculated when bpm of timer is set
#Override
public void run() {
long startTime = 0, elapsedTime = 0, threadSleepTime = 0;
running = true;
while (running) {
startTime = System.nanoTime();
tick();
elapsedTime = System.nanoTime() - startTime;
threadSleepTime = expectedTime - elapsedTime;
threadSleepTime = threadSleepTime < 0 ? 0 : threadSleepTime;
try { TimeUnit.NANOSECONDS.sleep(threadSleepTime); } catch (Exception e) { }
}
}
My biggest issue might have been, that I implemented the observer-interface in my JUnit testcase. So I created a private observer, that specifically counts the number of times, the tick was executed. The counter then stops my timer.
The testmethod measures the timing and asserts, that the needed time is somewhere between my defined limits.
It depends on how accurately you need to measure the time.
If you feel that it's "awkward" is that because you're not sure that the measurement is accurate enough? Do you fear that the OS is getting in the way with overhead?
If so, you may need an external timing board that's synchronized to an accurate source (GPS, atomic standard, etc.) to either test your code, or possibly to provide the trigger for your firing event.
Try this. You also need the time you are expecting. The expected time will be 1000000000/n where n is the number of times your timer needs to tick() per second.
public void run(){
long time = System.nanotime();
long elapsedTime = 0;
// Hope you need to tick 30 times per second
long expectedTime = 1000000000/30;
long waitTime = 0;
while (running){
tick();
elapsedTime = System.nanotime()-time;
waitTime = expectedTime-elapsedTime();
if (waitTime>0){
try { Thread.sleep(waitTime) } catch (Exception e){}
}
time = System.nanotime();
}
}
for(int i = 1; i < 10000; i++) {
Command nextCommand = getNextCommandToExecute();
}
I want to run the above program for 60 minutes. So instead of for loop I need to do something like-
long startTime = System.nanoTime();
do{
Command nextCommand = getNextCommandToExecute();
} while (durationOfTime is 60 minutes);
But I am not sure, how should I make this program to run for 60 miniutes.
Launch a background thread that sleeps for 60 minutes and exits:
Runnable r = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(60 * 60 * 1000L);
}
catch (InterruptedException e) {
// ignore: we'll exit anyway
}
System.exit(0);
}
}
new Thread(r).start();
<your original code here>
long startTime = System.currentTimeMillis();
do
{
//stuff
} while (System.currentTimeMillis() - startTime < 1000*60*60);
try the following:
long startTime = System.currentTimeMillis();
long endTime = startTime + (60*60*1000);
while(System.currentTimeMillis() <= endTime) {
Command nextCommand = getNextCommandToExecute();
}
One drawback with this method is if the Command you are trying to execute runs past the 60 minute timer or never finishes at all. If this behavior is not allowed, you are better off implementing a thread that interrupts whatever thread is running this loop.
long startTime = System.currentTimeMillis();
do{
Command nextCommand = getNextCommandToExecute();
}while (startTime < startTime+60*60*1000);
You could use:
long startTime = System.nanoTime();
do {
Command nextCommand = getNextCommandToExecute();
} while ((System.nanoTime() - startTime) < 60 * 60 * 1000000000L);
Please note System.nanoTime() is slightly different from using System.currentTimeMillis() not only in the scale, but also in what it measures: System.nanoTime() is the elapsed time, and System.currentTimeMillis() is the system time (wall clock). If the system time changes, System.currentTimeMillis() doesn't work as expected. (This doesn't apply to summertime change however, as the returned value is UTC / GMT.)
1000000000L nanoseconds is one second. Please note the L for long. In Java 7 you could also write the more readable 1_000_000_000L.
Here is my timer class, This class is designed to constantly update a timer in a view. However, when I run the app the first toast message is displayed to the screen but the second one is never reached (the timerTask's "run" method is never executed). I know that this is probably something simple that I am doing wrong. If anyone could steer me in the right direcion that would be great.
public class MyTimer {
static Timer _timerTask = new Timer();
static int totalSeconds = 1, hour = 0, min = 0, sec = 0;
static String mTimeFormat = "%02d:%02d:%02d";
static String timeTakenString;
public static void start (){
Toast.makeText(GPSMain.context, "Message one", Toast.LENGTH_LONG).show();
TimerTask timer = new TimerTask() {
#Override
public void run() {
Toast.makeText(GPSMain.context, "Message two", Toast.LENGTH_LONG).show();
totalSeconds += 1;
sec += 1;
if(sec >= 60) {
sec = 0;
min += 1;
if (min >= 60) {
min = 0;
hour += 1;
}
}
timeTakenString = String.format(mTimeFormat, hour, min, sec);
postExecute.sendEmptyMessage(0); //update UI
}
private Handler postExecute = new Handler(){
public void dispatchMessage(Message msg) {
super.dispatchMessage(msg);
GPSMain.timer.setText("Time Taken: "+timeTakenString);
}
};
};
_timerTask.scheduleAtFixedRate(timer,1000,1000);
}
}
code in another file calling this class:
MyTimer myTimer = new MyTimer();
....
myTimer.start();
PROJECT SPEC CHANGED!
My project leader changed the spec of the project so that it no longer needs to update the timer to the UI but rather display it as an end result. Accepting the first answer anyway as it solves the original problem. Will post the new code below.
New code calls:
System.currentTimeMillis();
at the beggining and end of the runcycle, which returns a long. The first value is then subtracted from the second value to calculate the amount of time taken to execute the runcycle. That value is then manipulated and put into a timer format that is displayed at the end as a string.
public static String getTimeTaken(long end, long start){
#SuppressWarnings("unused")
String formattedTime = "", hourHour = "", hourMin = ":", minSec = ":";
long timeTaken = (end-start)/1000, hour = 0, min = 0, sec = 0;
if (timeTaken>9 ){
hourHour = "0";
hourMin = ":0";
if (timeTaken>=60){
if (timeTaken>= 3200){
hour = timeTaken/3200;
timeTaken = timeTaken%3200;
if (hour>9){
hourHour = "";
}
}
min = timeTaken/60;
timeTaken = timeTaken%60;
if (min >9){
hourMin = ":";
}
}
sec = timeTaken;
if(sec%60<10){
minSec = ":0";
}
return formattedTime = (hourHour+hour+hourMin+min+minSec+sec);
}
sec = timeTaken;
minSec = ":0";
hourMin = ":0";
hourHour = "0";
return formattedTime = (hourHour+hour+hourMin+min+minSec+sec);
}
Using thread you cant update your UI for that you have to use runOnUiThread
youractivity.this.runOnUiThread(new Runnable(){public void run(){Toast.makeText(mContext, "Message", Toast.LENGTH_LONG).show();}});
(Very late...just answering in case someone reach this question... scheduling a task doesn't garantee it will run on the proper time... it may take longer, sometimes much longer...)
Hi I want to run code over a time period. For example i would like my code to do something like this.
for(every 5 minutes until i say to stop)
automatically read in new value for x
automatically read in new value for y
if (x==y)
//do something
if (x!=y)
//do something else
Timer is what you need.
Naive version. You might consider Timer or the quartz scheduler instead.
while (!done) {
try {
Thread.sleep(5 * 60 * 1000);
x = readX();
y = readY();
if (x == y) {
} else {
}
} catch(InterruptedException ie) {
}
}
System.currentTimeMillis(); Returns you the system time in milliseconds, you can use that.
but first, you need some sort of loop.
This is an alternative to Timer 's
public static final int SECONDS = 1000;
public static final int MINUTES = 60 * SECONDS;
boolean quit = false; //Used to quit when you want to..
long startTime = System.currentTimeMillis();
while (!quit) {
if (System.currentTimeMillis() >= (startTime + (long)5*MINUTES)) {
//automatically read in new value for x
//automatically read in new value for y
if (x==y) {
//do something
} else {
//do something else
}
startTime = System.currentTimeMillis(); //reset the timer for the next 5 minutes
}
}
How about:
Runnable runnable = new Runnable() {
public void run() {
// do your processing here
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(runnable, 0, 5, TimeUnit.MINUTES);
Call service.shutdown() when you want to stop.