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.
Related
I have a Runnable "NanoClock" class which keeps updating a private volatile double value in its run() method.
This class also has a getTime() method which returns the double value. Another class ("Master") is constructing the NanoClock class and creates a thread, as well as calling the start() method.
After it did this it calls the getTime() method several times (with a delay), but the value is not updating. What am I doing wrong?
NanoClock.java :
public class NanoClock implements Runnable {
private volatile boolean running;
private volatile double time;
public NanoClock() {
time = System.currentTimeMillis();
}
#Override
public void run() {
running = true;
while(running) {
try {
if(System.currentTimeMillis() > time) {
time = System.currentTimeMillis();
}
//This returns the updated value continuously when commented out
//System.out.println("Time: " + String.format("%.6f", unix_time));
Thread.sleep(2000);
} catch(Exception exc) {
exc.printStackTrace();
System.exit(1);
}
}
}
public double getTime() {
return time;
}
public void end() {
running = false;
}
}
Master.java:
public class Master {
public static void main(String[] args) {
try {
NanoClock nClock = new NanoClock();
Thread clockThread = new Thread(new NanoClock());
clockThread.setPriority(10);
clockThread.start();
//MY_ISSUE: This returns the same value every time
for(int a = 0; a < 10; a++) {
System.out.println("Time: " + nClock.getTime());
}
//MY_ISSUE: This cannot stop the while loop - I tested it with
//the println in the NanoClock class.
nClock.end();
System.out.println("Done!");
catch(Exception e) {
e.printStackTrace();
System.exit(1);
}
}
}
You've got two instances of NanoClock: one of them is an anonymous new NanoClock() which, as the Runnable in your other thread is happily keeping time in the backgound; the other is nClock, which is sitting idly by in the foreground in your main thread.
nClock should have been the Runnable in that other thread:
Thread clockThread = new Thread(nClock); // not new NanoClock()
This may not be the entire solution, but it should be a big step in the right direction.
System.currentTimeMillis() returns a long, but you store it in a double, which causes a loss of precision. When you change the member time (and also the return type of its getter) to a long you should get the expected result.
As a rule of thumb: When working with time units long is most appropriate datatype most of the time. Floating point numbers are not suitable to store precise results.
Thread.sleep(2000);
System.out.println("Time: " + nClock.getTime());
the for in main() must be sleep(2000)
If the code below will take 2 seconds, then the time will change.
//MY_ISSUE: This returns the same value every time
for(int a = 0; a < 10; a++) {
System.out.println("Time: " + nClock.getTime());
}
However a for loop with 10 iterations and a system.out will not even take a millisecond so it will not change.
Why 2 seconds? because you have a Thread.sleep in your runnable code.
Thread.sleep(2000);
Which means, the next update will be in 2 seconds.
And use System.nanoTime() instead of System.currentTimeMillis() since you really wanted nano time not millis.
Updated:
In my machine
public static void main(String args[]) {
long start = System.currentTimeMillis();
for(int a = 0; a < 10; a++) {
System.out.println("Iterating " + a);
}
long end = System.currentTimeMillis();
System.out.println("Start = " + start);
System.out.println("End = " + end);
}
Result, there is no difference in the start time and end time
Iterating 0
Iterating 1
Iterating 2
Iterating 3
Iterating 4
Iterating 5
Iterating 6
Iterating 7
Iterating 8
Iterating 9
Start = 1499592836298
End = 1499592836298
That code block executed so fast that it did not take even a single millisecond. Depending on the timing, it may take 1 millisecond.
Changing it to System.nanoTime()
public static void main(String args[]) {
long start = System.nanoTime();
for(int a = 0; a < 10; a++) {
System.out.println("Iterating " + a);
}
long end = System.nanoTime();
System.out.println("Start = " + start);
System.out.println("End = " + end);
}
Result, there is a difference in the start time and end time.
Iterating 0
Iterating 1
Iterating 2
Iterating 3
Iterating 4
Iterating 5
Iterating 6
Iterating 7
Iterating 8
Iterating 9
Start = 1012518090518837
End = 1012518091012960
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);
This is code which I have written to time how long it takes to perform a selection sort:
static public String [ ] selectionSort(String [ ] wordlist)
{
for (int i = 1; i < wordlist.length; i++)
{
int s = i-1;
for (int j = i; j < wordlist.length; j++)
{
if (wordlist[j].compareTo(wordlist[s]) < 0)
{
s = j;
}
}
String temp = wordlist[i-1];
wordlist[i-1] = wordlist[s];
wordlist[s] = temp;
}
return wordlist;
}
static public String [ ] timedSelectionSort(String [ ] wordlist)
{
long startTime = 0;
long stopTime = 0;
long elapsedMillis = 0;
long elapsedSec = 0;
long elapsedMin = 0;
startTime = System.currentTimeMillis();
wordlist = selectionSort(wordlist);
stopTime = System.currentTimeMillis();
elapsedMillis = stopTime-startTime;
elapsedSec = elapsedMillis/1000;
elapsedMin = elapsedMillis/60000;
System.out.printf("File reading took %d minutes and %s secs and %d milliseconds to execute\n",
elapsedMin,elapsedSec%60, elapsedMillis%1000);
System.out.println("Read " + wordlist.length + " strings.");
return wordlist;
}
I have to also time a how long it takes to make an arraylist object containing all of the strings in an array (my attempt is below)
static public ArrayList<String> makeArrayListClassObject(String [ ] wordlist)
{
long startTime = 0;
long stopTime = 0;
long elapsedMillis = 0;
long elapsedSec = 0;
long elapsedMin = 0;
startTime = System.currentTimeMillis();
ArrayList<String> stringList = new ArrayList<String>(Arrays.asList(wordlist));
stopTime = System.currentTimeMillis();
elapsedMillis = stopTime-startTime;
elapsedSec = elapsedMillis/1000;
elapsedMin = elapsedMillis/60000;
System.out.printf("File reading took %d minutes and %s secs and %d milliseconds to execute\n",
elapsedMin,elapsedSec%60, elapsedMillis%1000);
System.out.println("Read " + wordlist.length + " strings.");
return stringList;
}
as well as time how long it takes to sort the arraylist object using the Collections.sort( ) method. I have made the method (see below) but I don't know how to time it
static public void collectionsClassSort(ArrayList<String> arraylist)
{
Collections.sort(arraylist);
}
I guess my questions are:
1. Is there a way to use the same method to time these two methods the way I timed the first method?
2. If not, how can I time these two methods?
EDIT: the timed collections sort now works, but the timed building of the arraylist still does not. meaning that the timer says that the method took 0 minutes, 0 seconds, and 0 milliseconds to execute
This is the updated code for that:
static public ArrayList<String> makeArrayListClassObject(String [ ] wordlist)
{
long startTime = 0;
long stopTime = 0;
long elapsedMillis = 0;
long elapsedSec = 0;
long elapsedMin = 0;
startTime = System.currentTimeMillis();
ArrayList<String> stringList = new ArrayList<String>(Arrays.asList(wordlist));
stopTime = System.currentTimeMillis();
elapsedMillis = stopTime-startTime;
elapsedSec = elapsedMillis/1000;
elapsedMin = elapsedMillis/60000;
System.out.printf("File reading took %d minutes and %s secs and %d milliseconds to execute\n",
elapsedMin,elapsedSec%60, elapsedMillis%1000);
return stringList;
}
Why can't you just use something like this,
startTime = System.currentTimeMillis();
Collections.sort(arraylist);
stopTime = System.currentTimeMillis();
Its samething that you used above.
You need to distinguish between "doesn't work" and "doesn't produce a meaningful result".
It seems that your wordList string array is not large enough to notice time difference.
Two suggestions:
Test it with a much bigger array: hundreds of thousands of words (see my test code at the bottom)
Use System.nanoTime() that should yield better precision (see the explanation below).
From David Holmes' Weblog:
The absolute "time-of-day" clock is represented by the
System.currentTimeMillis() method, that returns a millisecond
representation of wall-clock time in milliseconds since the epoch. As
such it uses the operating system's "time of day" clock. The update
resolution of this clock is often the same as the timer interrupt (eg.
10ms), but on some systems is fixed, independent of the interrupt
rate.
The relative-time clock is represented by the System.nanoTime() method
that returns a "free-running" time in nanoseconds. This time is useful
only for comparison with other nanoTime values. The nanoTime method
uses the highest resolution clock available on the platform, and while
its return value is in nanoseconds, the update resolution is typically
only microseconds. However, on some systems there is no choice but to
use the same clock source as for currentTimeMillis() - fortunately
this is rare and mostly affects old Linux systems, and Windows 98.
You should always try to use nanoTime to do timing measurement or
calculation (and yes there are JDK API's that don't do this), in the
hope that it will have a better resolution than currentTimeMillis.
The following code produced "2" on my system:
import java.util.*;
public class ArrayTime {
public static void main(String[] args) {
String[] wordList = new String [600000];
for(int i=0; i<wordList.length; ++i)
wordList[i] = "" + i;
long start = System.currentTimeMillis();
ArrayList<String> stringList = new ArrayList<String>(Arrays.asList(wordList));
long elapsedTime = System.currentTimeMillis() - start;
System.out.println(elapsedTime);
}
}
I have an exercise that I am working on for programming class. I am getting an odd error that seems very basic, yet I am having trouble debugging it.
The code, when referenced, creates the standard StopWatch object with several instance methods associated with it. I created a main method at the bottom of the code in order to test each method in the StopWatch class to make sure it is working correctly.
Currently, when I run the program I get an error that says:
Exception in thread "main" java.lang.NoSuchMethodError: main.
I clearly have a main method in this class so I am not sure why I am getting this error.
The main method implements the Gambler's ruin program for testing. I am currently trying to test the stop() and elapsedTime() methods. The full code is enclosed below:
/* Notes:
* Start is the date of birth of the object. Most stopwatch don't keep track of when they were
* created.
*/
public class Stopwatch {
public long startTime; //The creation time of the stopwatch
public long totalTime; //Total time since watch was zeroed
boolean running = false; //This will flag if the watch is started or stopped
public Stopwatch() //First instance method called Stopwatch. What the client will use to create Stopwatch. This serves as the constructor.
{
start();
}
public void start()
{
startTime = System.currentTimeMillis();
running = true;
}
public void stop()
{
if(running) {
totalTime += System.currentTimeMillis() - startTime;
running = false;
}
}
public double elapsedTime()
{
if(running){
return System.currentTimeMillis() - startTime;
}
else{
return 0; //If the watch isn't currently running, return a 0 value.
}
}
public void zero()
{
totalTime = 0;
start();
}
public static void main(String[] args)
{
// Run T experiments that start with $stake and terminate on $0 or $goal.
Stopwatch program_time = new Stopwatch();
int stake = Integer.parseInt(args[0]);
int goal = Integer.parseInt(args[1]);
int T = Integer.parseInt(args[2]);
int bets = 0;
int wins = 0;
for (int t = 0; t < T; t++)
{
// Run one experiment
int cash = stake;
while (cash > 0 && cash < goal)
{
// Simulate one bet.
bets = bets + 1;
if (Math.random() < 0.5)
{
cash = cash + 1;
}
else
{
cash = cash - 1;
}
} // Cash is either going to be at $0 (ruin) or $goal (win)
if (cash == goal)
{
wins = wins + 1;
}
}
System.out.println(100 * wins / T + "% wins");
System.out.println("Avg # bets: " + bets/T);
program_time.stop();
System.out.println(program_time.elapsedTime());
}
}
Any thoughts?
Check the file and class names -- they must match exactly, even with upper and lower case.
Check whether the Classpath is correct or not.
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();
}
}