Server Help Forum Index Server Help
Community forums for Subgame, ASSS, and bots
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   StatisticsStatistics   RegisterRegister 
 ProfileProfile   Login to check your private messagesLogin to check your private messages   LoginLogin (SSL) 

Server Help | ASSS Wiki (0) | Shanky.com
Java Timer/Threads

 
Post new topic   Reply to topic Printable version
 View previous topic  Galaxian Prime Post :: Post Poopshoot?  View next topic  
Author Message
CypherJF
I gargle nitroglycerin


Gender:Gender:Male
Joined: Aug 14 2003
Posts: 2582
Location: USA
Offline

PostPosted: Wed Jun 22, 2005 10:54 pm   Post maybe stupid    Post subject: Java Timer/Threads Reply to topic Reply with quote

http://cypherjf.sscentral.com/

Quote:
06.22.2005 - Java, not as good as it should be?

Ive been trying to get my Java groove on, programming a bunch of prototypes - testing this and that. One of the applications was a Calendar that would highlight the current day - that should run 24/7 etc. However, after some testing I noticed a huge issue with Java that I would consider a "bug". I've been e-mailing my Java professor over the past few days trying to come up w/ a solution but here it is in short.

If you have a Thread or Runnable instance, including Timer, and you set your system time backwards (say by a day) - the application completely stops. If you set it forward, the thread will try and catch up to the system time - so it executes the appropriate event several rapid times (essentially going bezerk). I should mention here that .NET appears not to have this issue - but that is because I think it uses the GetTickCount() - or the API to determine how long the system has been running.

I'm not the only one who had this issue but it's been in existence since Java 1.3 from what I gather from this bug report:
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4290274

A sample block of code and it's run of when I set the system time forward:
Code: Show/Hide
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
System.out.println("---TIME---");
System.out.println("TIME:" + new Date());
System.out.println("//---TIME---");
} }, 10000, 10000);

Quote:
---TIME---
TIME:Tue Jun 21 14:08:33 EDT 2005
//---TIME---
---TIME---
TIME:Thu Jun 23 14:08:35 EDT 2005
//---TIME---
---TIME---
TIME:Thu Jun 23 14:08:35 EDT 2005
//---TIME---
---TIME---
TIME:Thu Jun 23 14:08:35 EDT 2005
//---TIME---

(same repeating - very very rapidly scrolling text - about 40 same entries)

//---TIME---
TIME:Thu Jun 23 14:08:36 EDT 2005
//---TIME---
---TIME---

(same repeating - very very rapidly scrolling text)

---TIME---
TIME:Thu Jun 23 14:08:37 EDT 2005
//---TIME---

(same repeating - very very rapidly scrolling text)

---TIME---
TIME:Thu Jun 23 14:08:38 EDT 2005
//---TIME---

(same repeating - very very rapidly scrolling text)

---TIME---
TIME:Thu Jun 23 14:08:38 EDT 2005
//---TIME---
---TIME---
TIME:Thu Jun 23 14:08:39 EDT 2005
//---TIME---

(same repeating - very very rapidly scrolling text)


Reference URLS:
http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/Timer.html
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4290274
_________________
Performance is often the art of cheating carefully. - James Gosling
Back to top
View users profile Send private message Add User to Ignore List
Cyan~Fire
I'll count you!
I'll count you!


Age:37
Gender:Gender:Male
Joined: Jul 14 2003
Posts: 4608
Location: A Dream
Offline

PostPosted: Wed Jun 22, 2005 11:39 pm   Post maybe stupid    Post subject: Reply to topic Reply with quote

Eh, Java sucks. Hey, I'm going to hijack your topic. Anybody know of an easy way to do function timing in Java?
_________________
This help is informational only. No representation is made or warranty given as to its content. User assumes all risk of use. Cyan~Fire assumes no responsibility for any loss or delay resulting from such use.
Wise men STILL seek Him.
Back to top
View users profile Send private message Add User to Ignore List Visit posters website
Cerium
Server Help Squatter


Age:43
Gender:Gender:Male
Joined: Mar 05 2005
Posts: 807
Location: I will stab you.
Offline

PostPosted: Thu Jun 23, 2005 3:32 am   Post maybe stupid    Post subject: Reply to topic Reply with quote

Well, the Timer class doesnt do anything that cant be duplicated. Since a fix may be a while off (and would no doubt break backwards comatibility with previous versions of java), youre left writing a custom Timer class.

You could copy/paste most of the code directly from Timer, but youd need to change the sched code. The bug page you posted already has a fairly good example of a workaround for the time being set backwards, but it needs to be updated.

wait time = ( Math.min( <calculated wait time>, <length between most frequent task executions>) );

That way at most, it would only wait the amount of time specified by the task that executes the most often.

Ignoring forward skips may be a bit harder, since a timer task could end up making the timer sleep for a very long time. Perhaps change the timer body it knows how long each iteration takes. Then, only sleep for a maximum of say 10 seconds each time it sleeps. If the 'iteraiton' time is longer than 10 seconds, you can assume the clock was set forward, and handling it accordingly.
The downside, is this may make some timers off by a few milliseconds, but hell, the Timer class shouldnt be used when you need tasks to be that accurate, anyway.

---

Cyan, I dunno if this is the best, or easiest, but this is what I use:

Code: Show/Hide

      int            intChecks      = 50;
      int            intIterations   = 25000;
      long[]         lngDuration      = new long[intChecks];
      double[]      dblRuntime      = new double[intChecks];
      DecimalFormat   objFormat      = new DecimalFormat("#.#####");

      // Setup variables and stuff here

      for(int intUpper = 0; intUpper < intChecks; ++intUpper)
      {
         long lngStart = System.currentTimeMillis();

         for(int intCounter = 0; intCounter < intIterations; ++intCounter)
         {
            // Code to time goes here
         }

         lngDuration[intUpper] = System.currentTimeMillis() - lngStart;
         dblRuntime[intUpper] = (double) lngDuration[intUpper] / (double) intIterations;

         System.out.println("Duration: " + lngDuration[intUpper]);
         System.out.println("Runtime:  " + objFormat.format(dblRuntime[intUpper]));
      }

      long   lngTotal = 0;
      double   dblTotal = 0;
      for(int intCounter = 0; intCounter < intChecks; ++intCounter)
      {
         lngTotal += lngDuration[intCounter];
         dblTotal += dblRuntime[intCounter];
      }


      System.out.println("-----");
      System.out.println();
      System.out.println("Avg Duration: " + (lngTotal / intChecks));
      System.out.println("Avg Runtime:  " + objFormat.format((dblTotal / intChecks)));


It gets more and more accurate the longer its allowed to run, but if anyone knows an even better way, lemme know =)
_________________
There are 7 user(s) ignoring me right now.
Back to top
View users profile Send private message Add User to Ignore List AIM Address
Dr Brain
Flip-flopping like a wind surfer


Age:39
Gender:Gender:Male
Joined: Dec 01 2002
Posts: 3502
Location: Hyperspace
Offline

PostPosted: Thu Jun 23, 2005 7:21 am   Post maybe stupid    Post subject: Reply to topic Reply with quote

Can't you just make yourself a Thread that has a sleep(10000); at the end of run()?
_________________
Hyperspace Owner

Smong> so long as 99% deaths feel lame it will always be hyperspace to me
Back to top
View users profile Send private message Add User to Ignore List AIM Address Yahoo Messenger MSN Messenger
Cerium
Server Help Squatter


Age:43
Gender:Gender:Male
Joined: Mar 05 2005
Posts: 807
Location: I will stab you.
Offline

PostPosted: Thu Jun 23, 2005 8:18 am   Post maybe stupid    Post subject: Reply to topic Reply with quote

Would work fine if your app only requires the one task. But when you start adding lots of tasks that need to be done at different intervals, you start running into problems.
Back to top
View users profile Send private message Add User to Ignore List AIM Address
Bak
?ls -s
0 in


Age:26
Gender:Gender:Male
Joined: Jun 11 2004
Posts: 1826
Location: USA
Offline

PostPosted: Thu Jun 23, 2005 10:07 am   Post maybe stupid    Post subject: Reply to topic Reply with quote

perhaps a cool linkedlist with sleep times and methods to run when the time runs out... so like If I wanted to run something in 10 seconds and something else in 7 seconds it would look like:


(7, func1) -> (3, func2) ->

then after func1 runs it could reschedule itself to run 10 seconds later which would be inserted into the linkedlist as:

(3, func2) -> (7, func1) ->
_________________
SubSpace Discretion: A Third Generation SubSpace Client
Back to top
View users profile Send private message Add User to Ignore List AIM Address
CypherJF
I gargle nitroglycerin


Gender:Gender:Male
Joined: Aug 14 2003
Posts: 2582
Location: USA
Offline

PostPosted: Thu Jun 23, 2005 1:01 pm   Post maybe stupid    Post subject: Reply to topic Reply with quote

No one is understanding what I am saying.

If you even have a "Thread", or a class that implements Runnable, it fails to work. Example:

Code: Show/Hide
import java.util.Date;

public class TestThread implements Runnable {
   private Thread thisThread;
   
   public static void main(String[] args) {
      TestThread tt = new TestThread();
      
      System.out.println("A test of a Thread that should sleep for 1 second.");
      tt.run();
   }
   
   public TestThread() {
      thisThread = new Thread(this, "Test");
      //thisThread.start();
   }
   
   public void run() {
      while (true) {
         System.out.println("" + new Date());
         try {
            Thread.sleep(1000);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}


Quote:
A test of a Thread that should sleep for 1 second.
Thu Jun 23 12:56:41 EDT 2005
Thu Jun 23 12:56:42 EDT 2005
Thu Jun 23 12:56:43 EDT 2005
Thu Jun 23 12:56:44 EDT 2005
Thu Jun 23 12:56:45 EDT 2005
Thu Jun 23 12:56:46 EDT 2005


When I switch my system clock to say June 21rst, it stops - because it uses the system time to calculate when it should notify the thread, etc.

edit:
I reset my clock back to today, and ran it then set it forward and backwards but it didn't appear to break anything. Grr. :shrug:
Back to top
View users profile Send private message Add User to Ignore List
Cerium
Server Help Squatter


Age:43
Gender:Gender:Male
Joined: Mar 05 2005
Posts: 807
Location: I will stab you.
Offline

PostPosted: Thu Jun 23, 2005 1:26 pm   Post maybe stupid    Post subject: Reply to topic Reply with quote

Well, sleep is a native function, so I would hope that its a bit more safe. But even still, it could be a race condition of sorts, in that when you were changing the time, you were getting lucky and the time was getting updated during the System.out.println call...

And bak, what you described is basicly how Timer works. Theres a list of objects to run. After an object is run, it iterates through the list and finds the object that should be run next. It uses System.currentTimeMillis() - (next runtime) to determine how far off the execution is, then sleeps.
Back to top
View users profile Send private message Add User to Ignore List AIM Address
CypherJF
I gargle nitroglycerin


Gender:Gender:Male
Joined: Aug 14 2003
Posts: 2582
Location: USA
Offline

PostPosted: Thu Jun 23, 2005 2:31 pm   Post maybe stupid    Post subject: Reply to topic Reply with quote

I don't trust the exact Date print, but eh for all I care I could have just had an incremental integer going. Its just a way to see that it was doing it's thing.

But I still find it funky the above Runnable code didn't work but then it now works. :shrug:. And it didn't work prior either because I had writen my own timer to throw "CypherTimerEvent" icon_smile.gif. But the thread wasn't executing right. :shrug:
Back to top
View users profile Send private message Add User to Ignore List
Dr Brain
Flip-flopping like a wind surfer


Age:39
Gender:Gender:Male
Joined: Dec 01 2002
Posts: 3502
Location: Hyperspace
Offline

PostPosted: Thu Jun 23, 2005 5:14 pm   Post maybe stupid    Post subject: Reply to topic Reply with quote

Code: Show/Hide

import java.util.*;

public class TimerTest {
   public static void main(String[] args) {
      BrainsTimer testTimer = new BrainsTimer(1000, 1000) {
         public boolean timerEventFired() {
            System.out.println("---TIME---");
            System.out.println("TIME:" + new Date());
            System.out.println("//---TIME---");
            return true;
         }
      };
   }
}

abstract class BrainsTimer extends Thread {
   private long delay;
   private long period;

   public BrainsTimer(long delay, long period) {
      this.delay = delay;
      this.period = period;
      this.start();
   }

   //returns true if it wishes to continue being scheduled
   public abstract boolean timerEventFired();

   public void run() {
      try {
         Thread.sleep(delay);
         while (timerEventFired()) {
            Thread.sleep(period);
         }
      }
      catch (InterruptedException e) {
         e.printStackTrace();
      }
   }
}
Back to top
View users profile Send private message Add User to Ignore List AIM Address Yahoo Messenger MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Server Help Forum Index -> Trash Talk All times are GMT - 5 Hours
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum
View online users | View Statistics | View Ignored List


Software by php BB © php BB Group
Server Load: 32 page(s) served in previous 5 minutes.

phpBB Created this page in 0.953947 seconds : 33 queries executed (92.1%): GZIP compression disabled