Java : mettre en pause en thread pour x millisecondes

a marqué ce sujet comme résolu.
Auteur du sujet

Bonjour,

je code actuellement un jeu en Java et j’ai un soucis avec l’exécution de thread. J’ai une classe Monstre qui implémente l’interface Runnable, dans cette classe la méthode run() permet de gérer son comportement.

Dans une autre classe, j’ai un code qui crée un Thread à partir d’un objet Monstre :

1
2
3
4
Thread monstreThread = new Thread(monstre);
if (!monstreThread.isAlive()) {
    monstreThread.start();
}

Jusque là, aucun soucis. C’est dans la classe Monstre que j’ai un problème, j’aimerais pouvoir mettre en pause l’exécution du thread de monstre pendant une période de temps en utilisant Thread.sleep() ou System.out.wait(). Le problème c’est que ça ne marche pas, j’ai essayé plusieurs façon, mais aucun résultat. Soit ça ne marche pas, soit c’est le thread principal qui est en pause.

En gros, je voudrais quelque chose comme ça dans Monstre:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public void run() {
   /* 
    * Après traitement, met en pause le thread de
    * monstre, et non pas le thread principal
    */

    try {
        Thread.sleep(2500);
    }
    catch(InterruptedException e) {
        e.getMessage()
    }
}

C’est possible de mettre en pause un thread d’une façon similaire ? Ou il faut peut-être bidouiller ? Merci :)

+0 -0
Auteur du sujet

Quelle est l’intérêt de mettre ce Thread en pause une fois les actions effectués ? Et il me semble que de la façon dont tu le décris ça devrait fonctionner.

WinXaito

J’ai oublié de préciser que le premier code est écrit dans une boucle, donc dès que le thread est mort, on en crée un nouveau tout de suite. C’est pour faire une pause après avoir appliqué des modifications à l’objet Monstre (déplacement, attaque, etc.).

+0 -0

C’est pour faire une pause après avoir appliqué des modifications à l’objet Monstre (déplacement, attaque, etc.).

Il serait mieux de passer par un listener car en mettant en pause le thread c’est pas très propre et ensuite à moins que tu fasses une boucle tu n’es pas assuré que l’action aie été effectué

+0 -0

C’est parce qu’il est impossible en Java qu’un Thread puisse gérer le cycle de vie d’un autre Thread (c’est à dire le killer, le mettre en pause etc…).

D’ailleurs, la méthode sleep() de la classe Thread est static ! Autrement dit, un Thread ne peut que s’endormir lui même. Il ne peut pas endormir un autre thread.

Il n’y a pas de solution "miracle" à ce genre de problème. J’entends par là que le développement des solutions robustes est complexe.

Pour que tes Threads puissent interagir les uns avec les autres, ils doivent communiquer leurs "intentions".

L’idée est de créer une classe gérant la vie de ton thread Monstre

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class MonsterRunnable implements Runnable {

private volatile int sleep = 0; // La variable indique le temps d'endormissement en millisecondes. 0 signifie qu'il n'est pas nécéssaire de s'endormir.
// On utilise également "volatile" car la variable dois être lue par deux threads différents.
// De même, on utilise un int pour que les affectations soient atomiques (ce ne serait pas forcément le cas avec un long de 64 bits)

public void monsterSleep(int sleep) {
    this.sleep = sleep;
}

@Override
public void run() {

    while(true) {

        if( this.sleep > 0) { // Si il faut s'endormir
            Thread.sleep((long) this.sleep);
            this.sleep = 0; // On remet à 0 pour indiquer qu'il n'est plus nécessaire de dormir
        }

        ... // le reste de tes actions dans la boucle

        }
    }
}

Le thread principal peut alors endormir le monstre thread :

1
2
3
4
5
6
7
8
public void run() {
   /* 
    * Après traitement, met en pause le thread de
    * monstre, et non pas le thread principal
    */

    monster.monsterSleep(2500);
}

Il y a toutefois quelques limitations. Comme tu le vois, la boucle du Runnable ne test s’il faut s’endormir qu’au début de chaque tour de boucle. Si l’appel à monsterSleep() a lieu pendant le traitement, ce traitement devra obligatoirement se terminer avant que le thread ne s’endorme. Cet inconvénient est également un avantage ! On s’assure qu’aucun traitement important ne pourra être interrompu en plein milieu.

Les mécanismes fournis par Java pour arrêter un thread, avec interrupt() et interrupted(), fonctionnent exactement sur le même principe. Voici la modification à apporter à ton Runnable pour qu’on puisse l’arrêter proprement.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Override
public void run() {

while(true) {

    if( Thread.interrupted() ) { // Si il a été demandé d'arrêter le thread
        return; // sort de la boucle, le Thread s'arrête
    }

    ... // le reste de tes actions dans la boucle

    }
}

On peut alors arrêter le thread proprement:

1
monster.interrupt(); // le thread va terminer son traitement en cours et s'arrèter

Édité par Sebajuste

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte