Alexiy
Alexiy

Reputation: 2040

One thread timing is faster than other

I have a thread which repeats an action each second (shooting):

long lasttime;
Creature owner;
public Attacker(Creature actor)
{
    super("Attacker - "+actor.getClass().getSimpleName());
    lasttime=System.currentTimeMillis();    
    owner=actor;
    owner.lockedon=true;
}
@Override
public void run() {
    super.run();
    while(!owner.dead && owner.lockedon)
    {
        List pl=TVS.getGameScreen().projectiles;
        synchronized (pl)
        {
           //here
            long curtime=System.currentTimeMillis();
            if(curtime-lasttime>1000)
            {
                owner.attack();
                lasttime=curtime;
            }
        }
    }
}

But when the main program thread slows down, this thread executes faster than main and shooting becomes too frequent relatively to the main thread. What should I do?

Upvotes: 0

Views: 102

Answers (2)

Raffaele Rossi
Raffaele Rossi

Reputation: 1109

I'd rather use Timers as they're easier to maintain and tends to be more accurate:

Timer shooterTimer = new Timer();
shooterTimer.scheduleAtFixedRate(
    new TimerTask() {
        @Override
        public void run() {
            if (!owner.dead && owner.lockedon) {
                List pl = TVS.getGameScreen().projectiles;
                synchronized (pl) {
                    onwer.attack();
                }
            }
        }
    },
    0,     // Start the timer now
    1000); // Execute the task every second

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533880

You are busy waiting, holding a lock which is likely to either consume a lot of CPU, or lock out other threads trying to use the same lock. I suggest something like

while(!owner.dead && owner.lockedon) {
    List pl=TVS.getGameScreen().projectiles;
    long curtime=System.currentTimeMillis();
    long remaining = 1000 - (curtime-lasttime);
    if(remaining <= 0) {
        synchronized (pl) { // only lock when needed.
            owner.attack();
            lasttime=curtime;
        }
    } else {
        // when not doing something useful, give up the CPU to another thread.
        Thread.sleep(remaining);
    }
}

Upvotes: 2

Related Questions