web-dev-qa-db-fra.com

NetBeans/Java/Nouveau conseil: Thread.sleep appelé en boucle

Dans NetBeans, un nouvel indice indique: Thread.sleep appelé en boucle.

Question 1: Comment/quand cela peut-il être un problème de dormir en boucle?

Question 2: Si c'est un problème, que dois-je faire à la place?

MISE À JOUR: Question 3: Voici du code. Dites-moi dans ce cas si je devrais utiliser autre chose que Thread.Sleep dans une boucle. En bref, cela est utilisé par un serveur qui écoute les connexions client TCP. Le sommeil est utilisé ici si le nombre maximal de sessions avec les clients est atteint. Dans ce cas, je souhaite que l'application attende qu'une session libre soit disponible.

public class SessionManager {
    private static final int DEFAULT_PORT = 7500;
    private static final int SLEEP_TIME = 200;
    private final DatabaseManager database = new DatabaseManager();
    private final ServerSocket serverSocket = new ServerSocket(DEFAULT_PORT);

public SessionManager() throws IOException, SQLException
{
}

public void listen()
{
while (true)
    if (Session.getSessionCount() < Session.getMaxSessionCount())
        try
        {
             new Thread(new Session(database, serverSocket.accept())).start();
        }
        catch (IOException ex) { ex.printStackTrace(); }
    else
        try
        {
            Thread.sleep(SLEEP_TIME);
        }
        catch (InterruptedException ex) { ex.printStackTrace(); }
}

public static void main(String[] args) throws IOException, SQLException
{
new SessionManager().listen();
}
}
46
asmo

L'appel en veille dans une boucle entraîne généralement des performances médiocres. Par exemple:

while (true) {
    if (stream.available() > 0) {
       // read input
    }
    sleep(MILLISECONDS);
}

Si MILLISECONDS est trop volumineux, ce code mettra longtemps à comprendre que la saisie est disponible.

Si MILLISECONDS est trop petit, ce code gaspille beaucoup de ressources système pour la vérification des entrées qui ne sont pas encore arrivées.

Les autres utilisations de sleep dans une boucle sont également discutables. Il y a généralement un meilleur moyen.

Si c'est un problème, que dois-je faire à la place?

Postez le code et peut-être que nous pourrons vous donner une réponse raisonnable.

MODIFIER

OMI, un meilleur moyen de résoudre le problème est d’utiliser un ThreadPoolExecutor .

Quelque chose comme ça:

public void listen() {
    BlockingQueue queue = new SynchronousQueue();
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
            1, Session.getMaxSessionCount(), 100, TimeUnit.SECONDS, queue);
    while (true) {
        try {
            queue.submit(new Session(database, serverSocket.accept()));
        } catch (IOException ex) { 
            ex.printStackTrace();
        }
    }
}

Ceci configure l'exécuteur pour qu'il corresponde à la façon dont votre code fonctionne actuellement. Vous pouvez le faire de plusieurs autres manières. voir le lien javadoc ci-dessus.

22
Stephen C

Comme d'autres l'ont dit, cela dépend de l'utilisation. Une utilisation légitime serait un programme conçu pour faire quelque chose toutes les 10 secondes (mais ce n’est pas si critique qu’un timing précis soit nécessaire). Nous avons beaucoup de ces "applications utilitaires" qui importent des données et d'autres tâches similaires toutes les quelques minutes. C’est un moyen facile d’exécuter ces tâches. Nous définissons généralement l’intervalle de veille très bas et utilisons un compteur pour que le programme reste réactif et puisse sortir facilement.

int count = 0;
while (true) {

    try {
        // Wait for 1 second.
        Thread.sleep(1000);
    }
    catch (InterruptedException ex) {}

    // Check to see if the program should exit due to other conditions.
    if (shouldExit())
        break;

    // Is 10 seconds up yet? If not, just loop back around.
    count++;
    if (count < 10) continue;

    // 10 seconds is up. Reset the counter and do something important.
    count = 0;
    this.doSomething();
}
3
java nut

Je pense avoir rencontré une utilisation tout à fait légitime de la méthode sleep() en boucle. 

Nous avons une connexion à sens unique entre serveur et client. Ainsi, lorsque le client souhaite établir une communication asynchrone avec le serveur, il envoie un message au serveur et interroge régulièrement le serveur pour obtenir une réponse. Il doit y avoir un intervalle de délai d'attente.

Response resp = null;
for (int i = 0; i < POLL_REPEAT && resp == null; i++) {
    try {
       Thread.sleep(POLL_INTERVAL);
    } catch (InterruptedException ie) {
    }
    resp = server.getResponse(workflowId);
}

POLL_REPEAT * POLL_INTERVAL ~ intervalle TIMEOUT

2
Ondrej Bozek

Comment/quand cela peut-il être un problème de dormir en boucle?
Les gens l’utilisent parfois à la place de méthodes de synchronisation appropriées (comme attendre/notifier).

Si c'est un problème, que dois-je faire à la place?
Cela dépend de ce que vous faites. Bien que ce soit difficile pour moi d’imaginer une situation dans laquelle cela est la meilleure approche, je suppose que cela est également possible.

Vous pouvez consulter le didacticiel de concurrence de Sun à ce sujet.

2
Nikita Rybak

Ce n'est pas la meilleure solution, mais vous pouvez réduire le nombre de millisecondes comme Thread.sleep(1);

0
Cergo