Reputation: 91
I'm teaching myself Java using one of the ebooks on Amazon. I was doing one of the lessons which does a "benchmark" of the computer. It does this by looping for a minute and calculating the results.
It basically doesn't show you anything for a minute until it's done. So my was making a small modification to show a dot as a progress bar of sorts every few seconds. Normally this is a trivial thing, but something's not right, and I don't know what.
What happens is miniIndex will reach the threshold I specified, and print the value of miniIndex and a period. Its then supposed to set miniIndex to zero so that counter can restart. But it doesn't reset, and never increments again. It's very odd behavior.
Here is the code in its entirety:
class Benchmark {
public static void main(String[] arguments) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
long index = 0;
// My inner index
int miniIndex = 0;
//
while (true) {
double x = Math.sqrt(index);
long now = System.currentTimeMillis();
if (now > endTime){
break;
}
index++;
// my modification
miniIndex++;
if (miniIndex >= 5000) {
System.out.print(miniIndex + ".");
miniIndex = 0;
}
// end of my modification
}
System.out.println(index + " loops in one minute.");
}
}
Upvotes: 8
Views: 1448
Reputation: 27
To see why it didn't work, you need to print the variable "now" while looping. You will notice that "now" stays the same for a certain amount while in the loop and eventually it will increment by one. So when you have one thousand of those increments it equates to a period of 1 sec. What the variable "miniIndex" is doing is counting up to 5000 loops and then resets, nowadays computers can perform thousands and thousands of loops in a second. Which is why it seemed like it wasn't resetting.
You can change the wait variable in the code to show different dot progress like you wanted.
class Main {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
long index = 0;
long wait = 5000; //secs 5000 == 5sec
long secondsPassed = startTime + wait;
System.out.print("counting");
while (true) {
double x = Math.sqrt(index);
long now = System.currentTimeMillis();
if (now > endTime){
break;
}
index++;
if (now >= secondsPassed) {
System.out.print(".");
secondsPassed = secondsPassed + wait;
}
}
System.out.println("");
System.out.println(index + " loops in one minute.");
}
}
Upvotes: 0
Reputation: 4667
I think you misunderstand what your miniIndex++
operation is doing, as it is not counting milliseconds but instead is counting the number of loop iterations which are not equal to each other. I have modified your code to execute the if
statement inside every 5 seconds, according to what you wanted to happen:
public static void main(String[] arguments) {
long startTime = System.currentTimeMillis();
long miniTime = startTime; //Declare miniTime equal to startTime
long endTime = startTime + 60000;
long index = 0;
while (true) {
double x = Math.sqrt(index);
long now = System.currentTimeMillis();
if (now > endTime){
break;
}
index++;
// my modification
//Current time minus last time the if executed and check if 5 seconds passed
if ((now - miniTime) >= 5000) {
miniTime = System.currentTimeMillis();
System.out.println("5 seconds have passed.");
//if you want to print the actual time elapsed every 5 seconds use this print
//System.out.println((now - startTime)/1000 + " seconds have passed.");
}
// end of my modification
}
System.out.println(index + " loops in one minute.");
}
Notice how I now compare current time of now
and subtract the miniTime
to check to see if it is higher than or equal 5000 milliseconds. To use time you must relate it to time somehow, in this case System.currentTimeMillis()
and the results. Numbers themselves such as counting the loop will never be time consistent.
A loop may execute millions of times, but only take 3 seconds.
Example Output:
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
5 seconds have passed.
16319642816 loops in one minute.
Note: 5 seconds have passed.
prints 11 times because at the 60 second mark the loop is broken so the final pass is not printed. (And 11 * 5
is 55 for the first 55 seconds).
Upvotes: 9
Reputation: 2641
You're probably overwhelming your output or something, such that it doesn't print anything at all. Your loop waits until 60000 milliseconds (1 minute). When I ran it, here was the end part of my output. Since your loop iterates very very fast (as fast as the computer can print, because that is the bottleneck here), NOT one iteration per second/millisecond, your counter miniIndex
goes up many many times per second. However, your code does work - it just doesn't do what you think it does.
If you try something like the following, you may get a slightly more precise output:
class Benchmark {
public static void main(String[] arguments) {
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
long index = 0;
// My inner index
int miniIndex = 0;
//
while (true) {
double x = Math.sqrt(index);
long now = System.currentTimeMillis();
if (now > endTime){
break;
}
index++;
// my modification
miniIndex++;
if (miniIndex >= 5000) {
System.out.print(miniIndex + ".");
miniIndex = 0;
}
// end of my modification
try {
Thread.sleep(1);
}
catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println(index + " loops in one minute.");
}
}
Output:
..........50976 loops in one minute.
Notice that you may not get 60,000 loops a minute, as Thread.sleep(1) can sleep for slightly over 1 millisecond.
Upvotes: 1
Reputation: 524
If you still want to use it in that type of output you can make it easier using StringBuilder
. It's coded like that:
StringBuilder stringBuilder = new StringBuilder();
and incide the loop like that:
if (miniIndex >= 5000) {
stringBuilder.append(miniIndex).append(".");
miniIndex = 0;
}
if (stringBuilder.length() >= 200) {
System.out.println(stringBuilder);
stringBuilder.setLength(0);
}
Upvotes: 3
Reputation: 9058
Your code is working fine; it's your expectations that are flawed.
Your code prints a dot every 5,000 iterations. Which is going to basically spew values. Remember, your CPU is running at something > 2 billion operations a second. You can probably do a few million of those loops per second. Call it a million loops per second, divided by 5000 is 200 dots per second, more or less, anyway.
Upvotes: 5