• Welcome to Overclockers Forums! Join us to reply in threads, receive reduced ads, and to customize your site experience!

Java, threads and lag...

Overclockers is supported by our readers. When you click a link to make a purchase, we may earn a commission. Learn More.

ssjwizard

Has slightly less legible writing than Thideras
Joined
Mar 12, 2002
Ok guys I am in the middle of building out a simple platformer as the next extension of my game engine. In my previous experiments particularly with snake I have used the Thread class to launch a cooldown timer and come back and release the cooldown.

In snake I used it to prevent buttons from being clicked twice via this code:

Code:
public class Button extends Label {

  private Texture active=null, inactive=null;
  private Actions action;
  private boolean cooldown = false;
  .
  .
  .
  protected void buttonCooldown(){
    cooldown = true;
    
    new Thread(new Runnable() {
      
      public void run(){
        try {
          Thread.sleep(200);
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
        finally{
          cooldown = false;
        }
      }
      
    } ).run();
  }//end buttonCooldown
  
  protected void buttonCooldown(final int howLong){
    cooldown = true;
    
    new Thread(new Runnable() {
      
      public void run(){
        try {
          Thread.sleep(howLong);
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
        finally{
          cooldown = false;
        }
      }
      
    } ).run();
  }//end buttonCooldown( how long )
  
  @Override
  public boolean isLeftClicked(){
    if(super.isLeftClicked() && !cooldown){
      buttonCooldown();
      return true;
    }
    else { return false; }
  }//end isClicked
  .
  .
  .
}

Alright now moving forward I am trying to do something similar with my Hero class to prevent erratic jumping behaviors/exploits.


Code:
public class Hero extends Dynamic_Tile {
  
  protected String heroName;
  protected int jumpCounter = 0, jumpSpeed = -18;
  protected boolean jumping = false, jumpCooldown = false;
  .
  .
  .
  public void setJumpSpeed(int s){
    jumpSpeed = s;
  }//jump speed properties
  public int getJumpSpeed(){ return jumpSpeed; }
  
  public void jump(){
    if (!jumpCooldown) {
      jumping = true;
      jumpCounter = 0;
      //jumpCooldown();
    }
  }//end jump
  
  public boolean isJumping(){ return jumping; }
  
  protected void jumpCooldown(){
    jumpCooldown = true;
    
    new Thread(new Runnable() {
      
      public void run(){
        try {
          Thread.sleep(1000);
        }
        catch (InterruptedException e) {
          e.printStackTrace();
        }
        finally{
          jumpCooldown = false;
        }
      }
      
    } ).run();
  }//end jump cooldown
  
  @Override
  public void draw(){
    super.draw();
    if(jumping){
      this.moveDynamic(0, jumpSpeed);
      this.jumpCounter++;
      if(this.topCollide() || jumpCounter > 15){
        jumping = false;
        jumpCooldown();
      }
    }
  }//end draw
  
  
}//end hero

now I have tried both putting the call to jumpCooldown in jump() and at the end of the action step currently residing in the draw() method. The problem is that as soon as the call to jumpCooldown() happens the entire duration of the sleep call hits the entire game. This did not happen in snake when a button was clicked everything else still moved fluidly.

Am I missing something in my knowledge of how a new thread is supposed to work? My assumption was that the new thread goes off into the Java VM does what it does and then terminates, meanwhile the rest of the primary execution thread continue to operate independently. I even went one step further and put the call to jumpCooldown in its own thread which did not fix my issue.

Well thanks in advance for taking the time to look at this, and I welcome your input on the matter.



note: 3 vertical dots indicate an omission of code.
 
Last edited:
Am I the only one who finds it somewhat laughable that Thread is not thread safe???

Ill check into using timers for this but I'm not sure how well that's going to work in this situation.
 
It's not laughable, if threads where thread safe the whole concept would not exist. In a single thread things happen in order, with many threads they don't, it's the whole idea :)
 
don't use threads, check at what time (use precise timers pls) you had a given input, if a newer input of the same kind gets registered before a set amount of time has passed, don't fire the event. profit? is this you want to achieve?

better not use threads. threads are EVIL! trust me . . .

edit: btw i hate java so i didn't look the code.
 
Threads can be very useful, but you have to understand what's happening and what the challenges regarding syncronization and race situations are, and why they exist.

Also, just so you know...

Thread.sleep() can be extremely dangerous if the application might create a lot of threads. For a local application where you know a lot of threads are never created it can be ok, but any distributed application with a lot of users could run out of threads very quickly, even if it's sleeping for a shorter while (I learnt this the hard way, so save yourself some embarasment and keep it in mind :) ).
 
don't use threads, check at what time (use precise timers pls) you had a given input, if a newer input of the same kind gets registered before a set amount of time has passed, don't fire the event. profit? is this you want to achieve?

better not use threads. threads are EVIL! trust me . . .

edit: btw i hate java so i didn't look the code.
edit2: and object creation is expensive, so better create a thread once and freeze unfreeze it when needed. i think java does some internal work when creating the same object over and over but it is just bad coding and should be avoided (if you try something like that in c# for example your application will slow down a lot).

still don't use threads for this, it's way simpler than it looks.
 
Since the thread starter is still just beginning programming, I'd consider "avoiding creating objects" unless targeted at a very specific use case to be quite bad advice. In java just about everything is an object, if you are going to try avoiding creating them you would be better off changing to another language (say Scala).

Sure there are cases when you should avoid creating new objects, but I'd first concentrate on understanding architecture, how objects work and interact and then start worrying about optimization. We have parts in the Application I work on that have millions of objects created a minute, and this is the optimized part. Sure passing on int's could have less overhead, but objects have the benefit that you can add validation in the constructor and fix problems in one place rather then everywhere touching it.

I also have a friend who does embedded computing, and tells me how he works at getting functions to be so small that it can be executed at one go with the cpu's registers, plays around with types or groups variables to save a byte of that 8KB of memory etc. There's a lot of levels in optimization. :D
 
Last edited:
Since the thread starter is still just beginning programming, I'd consider "avoiding creating objects" unless targeted at a very specific use case to be quite bad advice. In java just about everything is an object, if you are going to try avoiding creating them you would be better off changing to another language (say Scala).

nobody said to avoid creating objects, but repeatedly creating the same one is pointless. it's not just about the overhead of creating an object, you are also generating unecessary garbage that then needs to be collected.

Managed languages makes it possible, but this doesn't mean it should be abused.

you create the object once and store it somewhere for future use, not create it again every time you need it.

better not to start bad habits.

anyway, OP was this information useful?
 
Following your architecture, do something like
Code:
public class ButtonTimer implements Runnable {
 private JButton button;
 private double seconds;
 public ButtonTimer(JButton button, double seconds) {
  this.button = button;
 }
 public void run() {
  button.setDisabled();
  sleep(seconds * 1000);
  button.setEnabled();
 }
}
 
Back