How to program for a stopwatch [closed] - java

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I found this stopwatch java code from somewhere on the Internet, but it does not seem to be working. I was wondering how to fix this code to make it work. It's supposed to have features to start, stop and reset, and should display the time as hours:minutes:seconds.milliseconds (example: 12:35:17.26). Please help me.
public class StopWatch {
private long startTime = 0;
private long stopTime = 0;
private boolean running = false;
public void start() {
this.startTime = System.currentTimeMillis();
this.running = true;
}
public void stop() {
this.stopTime = System.currentTimeMillis();
this.running = false;
}
//elaspsed time in milliseconds
public long getElapsedTime() {
long elapsed;
if (running) {
elapsed = (System.currentTimeMillis() - startTime);
}
else {
elapsed = (stopTime - startTime);
}
return elapsed;
}
//elaspsed time in seconds
public long getElapsedTimeSecs() {
long elapsed;
if (running) {
elapsed = ((System.currentTimeMillis() - startTime) / 1000);
}
else {
elapsed = ((stopTime - startTime) / 1000);
}
return elapsed;
}
//sample usage
public static void main(String[] args) {
StopWatch s = new StopWatch();
s.start();
//code you want to time goes here
s.stop();
System.out.println("elapsed time in milliseconds: " + s.getElapsedTime());
}
}

This example shows how to start and stop a javax.swing.Timer. Several approaches to formatting are shown here. Reset is left as an exercise.

By the level of your assignment, sounds like your professor wants you to use nested loops, which are not being used in the example you took from the web.
I won't give you the full answer, but it's fairly simple: outer-most loop is for hours, the one inside hours is for minutes, the one inside minutes for seconds, and the one inside seconds for milliseconds. The inner-most loop (milliseconds), is the one that prints the current time.
Something like this:
// 24 hours in a day
for(int hours = 0; hours < 24; hours++)
{
// 60 mins in an hours
for(int minutes = 0; minutes < 60; minutes++)
{
// 60 secs in a min
for(int seconds = 0; seconds < 60; seconds++)
{
// 1000 ms in a sec.
for(int ms = 0; ms < 1000; ms++)
{
System.out.println(hours + ":" + minutes + ":" + seconds + "." + ms);
}
}
}
}
Now make it pretty and add a 1-millisecond delay in the inner-most loop and you are done! :)

If you want to make a stopwatch you must make a Thread. The Java API states all of the functions of a thread. This is necessary, because otherwise you won't be able to pause the timer. This is because the system spends the full runtime on the counting.
Also, the script you provided is used for determining the amount of time a certain calculation took, it's not ment for timing itself.
I suggest you make 2 classes, 1 for the timer and 1 for the GUI. make the GUI with a label, a start-, stop- and reset-button.
Next, make sure the timer-class EXTENDS THREAD (or implements Runnable) and make it a thread. Next implement the functions to either stop the thread or start the thread (your start/stop buttons). The Reset should be easy after that (just set the timer back to 0).
The StopWatch-class could look like this:
public class Stopwatch extends Thread
{
private long startTime;
private boolean started;
public void startThread()
{
this.startTime = System.currentTimeMillis();
this.started = true;
this.start();
}
public void run()
{
while (started)
{
// empty code since currentTimeMillis increases by itself
}
}
public int[] getTime()
{
long milliTime = System.currentTimeMillis() - this.startTime;
int[] out = new int[]{0, 0, 0, 0};
out[0] = (int)(milliTime / 3600000 );
out[1] = (int)(milliTime / 60000 ) % 60;
out[2] = (int)(milliTime / 1000 ) % 60;
out[3] = (int)(milliTime) % 1000;
return out;
}
public void stopThread()
{
this.started = false;
}
}
In the GUI-class you would make start call the 'startThread', stop call the StopWatch.stop(); (which is a Thread-function) and make reset call the reset().
This should get you started with a basic stopwatch. A (bad) example for its useage:
public static void main(String[] args) throws InterruptedException
{
Stopwatch s = new Stopwatch();
s.startThread();
while (true)
{
int[] curTime = s.getTime();
System.out.println(curTime[0] + " : " + curTime[1] + " : " + curTime[2] + " : " + curTime[3]);
}
}
It would actually be more sensible to do the calculations on the currentTimeMillis outside of the threadclass.

Related

StopWatch Class with methods

Alright so I'm still kind of new with methods so forgive me if this seems out of whack. I have a homework problem that has to be a stop watch class with two private data fields startTime and endTime. I need a method named start() that resets startTime to the current time and then stop() that resets endTime to the current time. I also need a getElapsed time method and returns the value.
This is what I got so far:
public class stopWatch {
private double startTime;
private double endTime;
public static void main(String[]args) {
}
public stopWatch(double startTime) {
startTime = System.currentTimeMillis();
}
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
endTime = System.currentTimeMillis();
}
public static void getElapsedTime(double startTime, double endTime){
stop() - start()
}
}
Could anybody please send me a step in the right direction? I know i need to subtract the start time from the stopped time and return that as the elapsed, I'm just not sure how to set it up properly.
Couple points.
startTime and endTime should be longs
Constructor should probably not take an argument.
start should probably set endTime to -1
getElapsedTime should be an instance method, not take arguments, return long and return endTime - startTime
to see it work, in your main, create a stopwatch, start the timer, call Thread.sleep(sometime), call stop, print out getElapsed.
I had to create the exact same thing. I wanted a simple Java stopwatch that would start running on my desktop. This is the code from the Stopwatch class. I added some formatting so it doesn't return long numbers that show how many milliseconds since you started the stopwatch. I assume that you would prefer to get something returned that is more meaningful to humans like seconds, minutes, and hours instead of milliseconds.
import java.text.DecimalFormat;
public class Stopwatch
{
// variables
private long startTime;
DecimalFormat twoDigits = new DecimalFormat("00"); // These help me return strings in the correct format
DecimalFormat threeDigits = new DecimalFormat("000"); // These help me return strings in the correct format
// Constructor
Stopwatch()
{
}
void start()
{
startTime = System.currentTimeMillis();
}
public long getStartTime()
{
return startTime;
}
public long getElapsedTime()
{
return System.currentTimeMillis() - startTime;
}
public String getElapsedTimeString()
{
return (String.valueOf(twoDigits.format(getHours())) + ":" + String.valueOf(twoDigits.format(getMinutes())) + ":" + String.valueOf(twoDigits.format(getSeconds())) + "." + String.valueOf(threeDigits.format(getMilliSeconds())));
}
public short getMilliSeconds()
{
return (short)((System.currentTimeMillis() - startTime) % 1000);
}
public byte getSeconds()
{
return (byte)(((System.currentTimeMillis() - startTime) / 1000) % 60);
}
public byte getMinutes()
{
return (byte)(((System.currentTimeMillis() - startTime) / 60000) % 60);
}
public long getHours()
{
return (System.currentTimeMillis() - startTime) / 3600000;
}
}

Running a counter thread in the background during a game

I am wondering the best way to keep a timer going in the background while a game is played.
I am programming a version of the HiLo game (in Java), which gives a user a certain amount of time to determine a number. If a guess is not correct, the game will tell the user whether the name is too high or too low.
I'm keeping track of time using System.currentTimeMillis() and seeing how much time has elapsed. This seems to work well, and so far I have been checking to see how much time has elapsed each time a new number is entered. For example, currently the app output looks like this:
Welcome to HiLo!
You have 10 seconds to guess a number I'm thinking of between 1 and 100.
> 67
Too high.
> 29
Too low.
Half of your time is gone! Only 5 seconds remains!
> 37
Too high.
> 33
Oops! Time is up - try again.
As you can see, currently, it can only check when I enter a new number how much time is passed.
I have tried creating a thread to start with a timer, however, when I start it, it keeps counting until the time is exhausted, without going on to the thread.run(int guess) which will be run when there is a new guess. I want to be able to still make guesses while the counter runs. Here is my attempt at a new implementation for thread.start():
public void start(int time_sent) throws InterruptedException {
time = time_sent;
startTime = (System.currentTimeMillis() / 1000);
while (1==1) {
long elapsed = ((System.currentTimeMillis() / 1000) - (startTime));
if (elapsed >= (time)) {
System.out.println("Oops! Time is up - try again.");
System.exit(0);
}
else if (elapsed >= (time/2) && !halfWarning) {
System.out.println("Half of your time is gone! Only " + (time/2) + " seconds remains!");
halfWarning = true;
}
}
}
How can I continue running this counter in the background?
This is one more approach:
public void game() {
Scanner scanner = new Scanner(System.in);
int time = 10; // sec
message("You have " + time + " seconds to guess...");
new Thread(new Background(System.currentTimeMillis() / 1000, time)).start();
while (true) {
String s = scanner.next();
if (s.equals("55")) {
message("You win");
System.exit(0);
} else {
message("try again...");
}
}
}
private void message(String str) {
System.out.println(str);
System.out.print("> "); // monit
}
You start 1 thread with behavior implemented in Background class. Next you enter while loop to capture user inputs. The Background thread works in background...
private class Background implements Runnable {
private long startTime;
private long time;
private boolean halfWarning;
private Background(long startTime, long time) {
this.startTime = startTime;
this.time = time;
}
#Override
public void run() {
while (true) {
long now = System.currentTimeMillis() / 1000;
long elapsed = now - startTime;
if (elapsed >= (time / 2) && !halfWarning) {
message("\n Half of your time is gone! Only " + (time / 2) + " seconds remains!");
halfWarning = true;
}
if (elapsed >= time) {
message("\n Oops! Time is up - try again.");
System.exit(0);
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
//ignore
}
}
}
}
Use a ScheduledExecutorService to execute concurrent actions in the future:
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> half = ses.schedule(new Runnable() {
#Override
public void run() {
System.out.println("Half of your time is gone!");
}
}, time / 2, TimeUnit.SECONDS);
ScheduledFuture<?> full = ses.schedule(new Runnable() {
#Override
public void run() {
System.out.println("Oops! Time is up - try again.");
// System.exit(0) ?
}
}, time, TimeUnit.SECONDS);
// check
if (input == toGuess) {
half.cancel();
full.cancel();
}
You could have a Timer thread that prints out these messages and shuts down the listening program.
It might inspire you :
public static class Game extends TimerTask {
private long start;
private long end;
public Game(long end) {
super();
this.start = System.currentTimeMillis();
this.end = end;
}
#Override
public void run() {
while (System.currentTimeMillis() - start < end)
System.out.println(System.currentTimeMillis());
}
}
public static void main(String[] args) {
TimerTask task = new Game(10000);
Timer timer = new Timer();
timer.schedule(task,0);
}

how I can exit from a loop in one second using Runtime?

how I can exit from a loop in one second using Runtime?
I want use this code
public class test {
public static void main(String[] args) {
Runtime runtime = Runtime.getRuntime();
long usedMemory = runtime.totalMemory()-runtime.freeMemory();
int mbytes = (int) usedMemory/1000; // Used memory (Mbytes)
String str="a";
while (somthing < one second ) {
}
}
long startTime = System.currentTimeMillis();
while((System.currentTimeMillis()-startTime)<=1000){
str=str + "a";
}
ok to do this you need to records the start time, and then compare it to the current time as you go.
long start = System.currentTimeMillis();
String str="a";
while (true) {
long now = System.currentTimeMillis();
if (now - start > 1000)
break;
// do your stuff
str=str + "a";
}
System.out.println (str);
The above code will probably spend more time getting the time that doing the stuff you want though
long startTime = System.currentTimeMillis();
while((System.currentTimeMillis()-startTime)<1000){
// Your task goes here
}
Write your code in while loop. It will exit the loop after 1 second.
long start = System.currentTimeMillis();
long end = start + 1000; // 1000 ms/sec
while (System.currentTimeMillis() < end)
{
// Write your code here
}
i think that you can use something like this if you don't really need to use Runtime.
public class test {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long currentTime = System.currentTimeMillis();
long usedMemory = runtime.totalMemory()-runtime.freeMemory();
int mbytes = (int) usedMemory/1000; // Used memory (Mbytes)
String str="a";
while (currentTime-startTime<1000) {
currentTime = System.currentTimeMillis();
}
}

System.nanoTime vs System.currentTimeMillis

According to its documentation, System.nanoTime returns
nanoseconds since some fixed but arbitrary origin time. However, on all x64 machines I tried the code below, there were time jumps, moving that fixed origin time around. There may be some flaw in my method to acquire the correct time using an alternative method (here, currentTimeMillis). However, the main purpose of measuring relative times (durations) is negatively affected, too.
I came across this problem trying to measure latencies when comparing different queues to LMAX's Disruptor where I got very negative latencies sometimes. In those cases, start and end timestamps were created by different threads, but the latency was computed after those threads had finished.
My code here takes time using nanoTime, computes the fixed origin in currentTimeMillis time, and compares that origin between calls. And since I must ask a question here: What is wrong with this code? Why does it observe violations of the fixed origin contract? Or does it not?
import java.text.*;
/**
* test coherency between {#link System#currentTimeMillis()} and {#link System#nanoTime()}
*/
public class TimeCoherencyTest {
static final int MAX_THREADS = Math.max( 1, Runtime.getRuntime().availableProcessors() - 1);
static final long RUNTIME_NS = 1000000000L * 100;
static final long BIG_OFFSET_MS = 2;
static long startNanos;
static long firstNanoOrigin;
static {
initNanos();
}
private static void initNanos() {
long millisBefore = System.currentTimeMillis();
long millisAfter;
do {
startNanos = System.nanoTime();
millisAfter = System.currentTimeMillis();
} while ( millisAfter != millisBefore);
firstNanoOrigin = ( long) ( millisAfter - ( startNanos / 1e6));
}
static NumberFormat lnf = DecimalFormat.getNumberInstance();
static {
lnf.setMaximumFractionDigits( 3);
lnf.setGroupingUsed( true);
};
static class TimeCoherency {
long firstOrigin;
long lastOrigin;
long numMismatchToLast = 0;
long numMismatchToFirst = 0;
long numMismatchToFirstBig = 0;
long numChecks = 0;
public TimeCoherency( long firstNanoOrigin) {
firstOrigin = firstNanoOrigin;
lastOrigin = firstOrigin;
}
}
public static void main( String[] args) {
Thread[] threads = new Thread[ MAX_THREADS];
for ( int i = 0; i < MAX_THREADS; i++) {
final int fi = i;
final TimeCoherency tc = new TimeCoherency( firstNanoOrigin);
threads[ i] = new Thread() {
#Override
public void run() {
long start = getNow( tc);
long firstOrigin = tc.lastOrigin; // get the first origin for this thread
System.out.println( "Thread " + fi + " started at " + lnf.format( start) + " ns");
long nruns = 0;
while ( getNow( tc) < RUNTIME_NS) {
nruns++;
}
final long runTimeNS = getNow( tc) - start;
final long originDrift = tc.lastOrigin - firstOrigin;
nruns += 3; // account for start and end call and the one that ends the loop
final long skipped = nruns - tc.numChecks;
System.out.println( "Thread " + fi + " finished after " + lnf.format( nruns) + " runs in " + lnf.format( runTimeNS) + " ns (" + lnf.format( ( double) runTimeNS / nruns) + " ns/call) with"
+ "\n\t" + lnf.format( tc.numMismatchToFirst) + " different from first origin (" + lnf.format( 100.0 * tc.numMismatchToFirst / nruns) + "%)"
+ "\n\t" + lnf.format( tc.numMismatchToLast) + " jumps from last origin (" + lnf.format( 100.0 * tc.numMismatchToLast / nruns) + "%)"
+ "\n\t" + lnf.format( tc.numMismatchToFirstBig) + " different from first origin by more than " + BIG_OFFSET_MS + " ms"
+ " (" + lnf.format( 100.0 * tc.numMismatchToFirstBig / nruns) + "%)"
+ "\n\t" + "total drift: " + lnf.format( originDrift) + " ms, " + lnf.format( skipped) + " skipped (" + lnf.format( 100.0 * skipped / nruns) + " %)");
}};
threads[ i].start();
}
try {
for ( Thread thread : threads) {
thread.join();
}
} catch ( InterruptedException ie) {};
}
public static long getNow( TimeCoherency coherency) {
long millisBefore = System.currentTimeMillis();
long now = System.nanoTime();
if ( coherency != null) {
checkOffset( now, millisBefore, coherency);
}
return now - startNanos;
}
private static void checkOffset( long nanoTime, long millisBefore, TimeCoherency tc) {
long millisAfter = System.currentTimeMillis();
if ( millisBefore != millisAfter) {
// disregard since thread may have slept between calls
return;
}
tc.numChecks++;
long nanoMillis = ( long) ( nanoTime / 1e6);
long nanoOrigin = millisAfter - nanoMillis;
long oldOrigin = tc.lastOrigin;
if ( oldOrigin != nanoOrigin) {
tc.lastOrigin = nanoOrigin;
tc.numMismatchToLast++;
}
if ( tc.firstOrigin != nanoOrigin) {
tc.numMismatchToFirst++;
}
if ( Math.abs( tc.firstOrigin - nanoOrigin) > BIG_OFFSET_MS) {
tc.numMismatchToFirstBig ++;
}
}
}
Now I made some small changes. Basically, I bracket the nanoTime calls between two currentTimeMillis calls to see if the thread has been rescheduled (which should take more than currentTimeMillis resolution). In this case, I disregard the loop cycle. Actually, if we know that nanoTime is sufficiently fast (as on newer architectures like Ivy Bridge), we can bracket in currentTimeMillis with nanoTime.
Now the long >10ms jumps are gone. Instead, we count when we get more than 2ms away from first origin per thread. On the machines I have tested, for a runtime of 100s, there are always close to 200.000 jumps between calls. It is for those cases that I think either currentTimeMillis or nanoTime may be inaccurate.
As has been mentioned, computing a new origin each time means you are subject to error.
// ______ delay _______
// v v
long origin = (long)(System.currentTimeMillis() - System.nanoTime() / 1e6);
// ^
// truncation
If you modify your program so you also compute the origin difference, you'll find out it's very small. About 200ns average I measured which is about right for the time delay.
Using multiplication instead of division (which should be OK without overflow for another couple hundred years) you'll also find that the number of origins computed that fail the equality check is much larger, about 99%. If the reason for error is because of the time delay, they would only pass when the delay happens to be identical to the last one.
A much simpler test is to accumulate elapsed time over some number of subsequent calls to nanoTime and see if it checks out with the first and last calls:
public class SimpleTimeCoherencyTest {
public static void main(String[] args) {
final long anchorNanos = System.nanoTime();
long lastNanoTime = System.nanoTime();
long accumulatedNanos = lastNanoTime - anchorNanos;
long numCallsSinceAnchor = 1L;
for(int i = 0; i < 100; i++) {
TestRun testRun = new TestRun(accumulatedNanos, lastNanoTime);
Thread t = new Thread(testRun);
t.start();
try {
t.join();
} catch(InterruptedException ie) {}
lastNanoTime = testRun.lastNanoTime;
accumulatedNanos = testRun.accumulatedNanos;
numCallsSinceAnchor += testRun.numCallsToNanoTime;
}
System.out.println(numCallsSinceAnchor);
System.out.println(accumulatedNanos);
System.out.println(lastNanoTime - anchorNanos);
}
static class TestRun
implements Runnable {
volatile long accumulatedNanos;
volatile long lastNanoTime;
volatile long numCallsToNanoTime;
TestRun(long acc, long last) {
accumulatedNanos = acc;
lastNanoTime = last;
}
#Override
public void run() {
long lastNanos = lastNanoTime;
long currentNanos;
do {
currentNanos = System.nanoTime();
accumulatedNanos += currentNanos - lastNanos;
lastNanos = currentNanos;
numCallsToNanoTime++;
} while(currentNanos - lastNanoTime <= 100000000L);
lastNanoTime = lastNanos;
}
}
}
That test does indicate the origin is the same (or at least the error is zero-mean).
As far as I know the method System.currentTimeMillis() makes indeed sometimes jumps, dependent on the underlying OS. I have observed this behaviour myself sometimes.
So your code gives me the impression you try to get the offset between System.nanoTime() and System.currentTimeMillis() repeated times. You should rather try to observe this offset by calling System.currentTimeMillis() only once before you can say that System.nanoTimes() causes sometimes jumps.
By the way, I will not pretend that the spec (javadoc describes System.nanoTime() related to some fixed point) is always perfectly implemented. You can look on this discussion where multi-core CPUs or changes of CPU-frequencies can negatively affect the required behaviour of System.nanoTime(). But one thing is sure. System.currentTimeMillis() is far more subject to arbitrary jumps.

Issues with using too many Threads a benchmark program

I've programmed a (very simple) benchmark in Java. It simply increments a double value up to a specified value and takes the time.
When I use this singlethreaded or with a low amount of threads (up to 100) on my 6-core desktop, the benchmark returns reasonable and repeatable results.
But when I use for example 1200 threads, the average multicore duration is significantly lower than the singlecore duration (about 10 times or more). I've made sure that the total amount of incrementations is the same, no matter how much threads I use.
Why does the performance drop so much with more threads? Is there a trick to solve this problem?
I'm posting my source, but I don't think, that there is a problem.
Benchmark.java:
package sibbo.benchmark;
import java.text.DecimalFormat;
import java.util.LinkedList;
import java.util.List;
public class Benchmark implements TestFinishedListener {
private static final double TARGET = 1e10;
private static final int THREAD_MULTIPLICATOR = 2;
public static void main(String[] args) throws InterruptedException {
Benchmark b = new Benchmark(TARGET);
b.start();
}
private int coreCount;
private List<Worker> workers = new LinkedList<>();
private List<Worker> finishedWorkers = new LinkedList<>();
private double target;
public Benchmark(double target) {
this.target = target;
getSystemInfos();
printInfos();
}
private void getSystemInfos() {
coreCount = Runtime.getRuntime().availableProcessors();
}
private void printInfos() {
System.out.println("Usable cores: " + coreCount);
System.out.println("Multicore threads: " + coreCount * THREAD_MULTIPLICATOR);
System.out.println("Loops per core: " + new DecimalFormat("###,###,###,###,##0").format(TARGET));
System.out.println();
}
public synchronized void start() throws InterruptedException {
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
System.out.print("Initializing singlecore benchmark... ");
Worker w = new Worker(this, 0);
workers.add(w);
Thread.sleep(1000);
System.out.println("finished");
System.out.print("Running singlecore benchmark... ");
w.runBenchmark(target);
wait();
System.out.println("finished");
printResult();
System.out.println();
// Multicore
System.out.print("Initializing multicore benchmark... ");
finishedWorkers.clear();
for (int i = 0; i < coreCount * THREAD_MULTIPLICATOR; i++) {
workers.add(new Worker(this, i));
}
Thread.sleep(1000);
System.out.println("finished");
System.out.print("Running multicore benchmark... ");
for (Worker worker : workers) {
worker.runBenchmark(target / THREAD_MULTIPLICATOR);
}
wait();
System.out.println("finished");
printResult();
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
}
private void printResult() {
DecimalFormat df = new DecimalFormat("###,###,###,##0.000");
long min = -1, av = 0, max = -1;
int threadCount = 0;
boolean once = true;
System.out.println("Result:");
for (Worker w : finishedWorkers) {
if (once) {
once = false;
min = w.getTime();
max = w.getTime();
}
if (w.getTime() > max) {
max = w.getTime();
}
if (w.getTime() < min) {
min = w.getTime();
}
threadCount++;
av += w.getTime();
if (finishedWorkers.size() <= 6) {
System.out.println("Worker " + w.getId() + ": " + df.format(w.getTime() / 1e9) + "s");
}
}
System.out.println("Min: " + df.format(min / 1e9) + "s, Max: " + df.format(max / 1e9) + "s, Av per Thread: "
+ df.format((double) av / threadCount / 1e9) + "s");
}
#Override
public synchronized void testFinished(Worker w) {
workers.remove(w);
finishedWorkers.add(w);
if (workers.isEmpty()) {
notify();
}
}
}
Worker.java:
package sibbo.benchmark;
public class Worker implements Runnable {
private double value = 0;
private long time;
private double target;
private TestFinishedListener l;
private final int id;
public Worker(TestFinishedListener l, int id) {
this.l = l;
this.id = id;
new Thread(this).start();
}
public int getId() {
return id;
}
public synchronized void runBenchmark(double target) {
this.target = target;
notify();
}
public long getTime() {
return time;
}
#Override
public void run() {
synWait();
value = 0;
long startTime = System.nanoTime();
while (value < target) {
value++;
}
long endTime = System.nanoTime();
time = endTime - startTime;
l.testFinished(this);
}
private synchronized void synWait() {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
You need to understand that the OS (or Java thread scheduler, or both) is trying to balance between all of the threads in your application to give them all a chance to perform some work, and there is a non-zero cost to switch between threads. With 1200 threads, you have just reached (and probably far exceeded) the tipping point wherein the processor is spending more time context switching than doing actual work.
Here is a rough analogy:
You have one job to do in room A. You stand in room A for 8 hours a day, and do your job.
Then your boss comes by and tells you that you have to do a job in room B also. Now you need to periodically leave room A, walk down the hall to room B, and then walk back. That walking takes 1 minute per day. Now you spend 3 hours, 59.5 minutes working on each job, and one minute walking between rooms.
Now imagine that you have 1200 rooms to work in. You are going to spend more time walking between rooms than doing actual work. This is the situation that you have put your processor into. It is spending so much time switching between contexts that no real work gets done.
EDIT: Now, as per the comments below, maybe you spend a fixed amount of time in each room before moving on- your work will progress, but the number of context switches between rooms still affects the overall runtime of a single task.
Ok, I think I've found my problem, but until now, no solution.
When measuring the time every thread runs to do his part of the work, there are different possible minimums for different total amounts of threads. The maximum is the same everytime. In case that a thread is started first and then is paused very often and finishes last. For example this maximum value could be 10 seconds. Assuming that the total amount of operations that is done by every thread stays the same, no matter how much threads I use, the amount of operations that is done by a single thread has to be changed when using a different amount of threads. For example, using one thread, it has to do 1000 operations, but using ten threads, everyone of them has to do just 100 operations. Now, using ten threads, the minimum amount of time that one thread can use is much lower than using one thread. So calculating the average amount of time every thread needs to do his work is nonsense. The minimum using ten Threads would be 1 second. This happens if one thread does its work without interruption.
EDIT
The solution would be to simply measure the amount of time between the start of the first thread and the completion of the last.

Categories

Resources