Guilherme Garcia da Rosa
Guilherme Garcia da Rosa

Reputation: 1030

Why my thread only execute once even if its in an infinite loop?

Well, my thread was running only once, so I realized I forgot to put it inside an loop, so I did, put it into an while{true} loop, but still it only repeats once.

Here is my code:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package snake.multiplayer;

import java.util.ArrayList;

/**
 *
 * @author GUIAKI
 */
public class movimentacoes implements Runnable {
    Jogo jogo;
    ArrayList<Player> players = new ArrayList<Player>();
    int qtdadePlayers;
    long lastTime;
    long delay;
    long millis(){
        return System.currentTimeMillis() % 1000;
    }
    public void run(){
        int i;
        while(true){
            if(lastTime-millis()>=delay){
                for(i=0;i<qtdadePlayers;i++){
                    players.get(i).anda();
                    System.out.println("Printou");
                }
                jogo.repaint();
                //checaColisao();
                lastTime=millis();
            }
        }
    }
}

and here is where I call it:

    Mov = new movimentacoes();
    Mov.players.add(0,new Player(500,500,playimg.getImage(),15));
    Mov.qtdadePlayers=1;
    Mov.lastTime=System.currentTimeMillis() % 1000;
    Mov.delay=50;
    Mov.jogo=this;
    Thread t1 = new Thread(Mov);
    t1.start();

The most odd thing, is that if I debug the code, it runs repeatedly if I still debug it.

How can I make it keep running?

Upvotes: 0

Views: 145

Answers (4)

TwoThe
TwoThe

Reputation: 14269

What you want to do is to periodically call a Runnable and execute it. You can have a thread run infinitely in a loop and check the time, however this model wastes a lot of CPU time by asking for the time (actually 100% CPU) and even if you include a Thread.sleep() there is no guarantee that it is woken up on time. A much better way is to schedule a task at a fixed rate. Java can do this with the ScheduledExecutorService.

In your case the run method becomes:

public void run(){
  for(int i=0;i<qtdadePlayers;i++){
    players.get(i).anda();
    System.out.println("Printou");
  }
  jogo.repaint();
}

And then you need to schedule it in an Executor like this:

final ScheduledExecutorService executor = Executors.newScheduledThreadPool(NUM_THREADS); // 1 threads is probably enough for your case
// ...
executor.scheduleAtFixedRate(new Movimentacoes(), 0, delay, TimeUnit.MILLISECONDS);

To stop the Runnable once your program terminates, you call executor.shutdown(). After this call any Runnables currently in progress will receive an interrupted status and no further calls are scheduled. The program will eventually terminate, once all currently still running Runnables have finished their run method. So in case your code takes a while, you might want to query Thread.interrupted().

Upvotes: 0

Paperwaste
Paperwaste

Reputation: 685

wont lastTime-millis() be a negative value? because millis is time in the future to lastTime

change it to millis()-lastTime

Upvotes: 1

prmottajr
prmottajr

Reputation: 1824

Your code seems ok, there are 2 things that could happen:

1 - for some reasong the thread throws an exception and that would abort the thread

2 - you are running some old version of the compiled code (this could be because the debug version could be in a different folder than the release)

Try to clean and rebuild your project.

Upvotes: 0

Guilherme Garcia da Rosa
Guilherme Garcia da Rosa

Reputation: 1030

In the method:

public void run(){

the condition:

if(lastTime-millis()>=delay){

will start to get negative values once it runs more than once, so its needed to change the order:

if(millis()-lastTime>=delay){

Than it all works as it should, thanks Sotirios Delimanolis.

Upvotes: 2

Related Questions