92 votes

Est-il légal d'appeler la méthode start deux fois sur le même thread?

Le code suivant mène à la "java.lang.IllegalThreadStateException: Fil déjà commencé." la deuxième fois qu'il est exécuté par le programme.

updateUI.join();    

if (!updateUI.isAlive()) 
    updateUI.start();

Ce qui se passe à la deuxième temps d' updateUI.start() est appelé. J'ai franchi plusieurs fois, et le thread est appelé et complètement effectue un cycle complet avant de frapper updateUI.start().

Appelant updateUI.run() évite l'erreur, mais provoque le thread à exécuter dans le thread de l'INTERFACE utilisateur (le thread appelant, comme mentionné dans d'autres postes sur), ce qui n'est pas ce que je veux.

Un Fil être commencé qu'une seule fois? Si donc, que ce que dois-je faire si je veux exécuter le fil à nouveau? Ce thread est en train de faire certains calculs dans le fond, si je ne le fais pas dans le thread que c'est fait dans le thread de l'INTERFACE utilisateur et l'utilisateur dispose d'un trop long d'attendre.

118voto

coobird Points 70356

À partir de la Spécification de l'API Java pour l' Thread.start méthode:

Il n'est jamais juridiques pour démarrer un thread plus d'une fois. En particulier, un fil peut ne pas être redémarré une fois que c' a terminé son exécution.

En outre:

Jette:
IllegalThreadStateException - si le thread a été déjà commencé.

Donc oui, un Thread ne peut être lancé qu'une seule fois.

Si que que dois-je faire si je veux exécutez le fil à nouveau?

Si un Thread doit être exécuté plus d'une fois, on doit faire une nouvelle instance de l' Thread et appelez - start .

14voto

Bob Cross Points 13552

Tout à fait exact. À partir de la documentation:

Il n'est jamais juridiques pour démarrer un thread plus d'une fois. En particulier, un fil peut ne pas être redémarré une fois que c' a terminé son exécution.

En termes de ce que vous pouvez faire pour répéter le calcul, il me semble que si vous pouvez utiliser SwingUtilities invokeLater méthode. Vous êtes déjà à l'essai en appelant run() directement, ce qui signifie que vous êtes déjà à penser à l'aide d'un Runnable plutôt qu'une brute Thread. Essayez d'utiliser l' invokeLater méthode sur l' Runnable de la tâche et de voir si cela correspond à votre schéma mental un peu mieux.

Voici l'exemple de la documentation:

 Runnable doHelloWorld = new Runnable() {
     public void run() {
         // Put your UI update computations in here.
         // BTW - remember to restrict Swing calls to the AWT Event thread.
         System.out.println("Hello World on " + Thread.currentThread());
     }
 };

 SwingUtilities.invokeLater(doHelloWorld);
 System.out.println("This might well be displayed before the other message.");

Si vous remplacez println appel avec votre calcul, c'est peut-être exactement ce dont vous avez besoin.

EDIT: suite aux commentaires, je n'avais pas remarqué le Android balise dans le post original. L'équivalent de invokeLater dans l'Android travail est - Handler.post(Runnable). De son javadoc:

/**
 * Causes the Runnable r to be added to the message queue.
 * The runnable will be run on the thread to which this handler is
 * attached.
 *
 * @param r The Runnable that will be executed.
 *
 * @return Returns true if the Runnable was successfully placed in to the
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.
 */

Ainsi, dans le monde Android, vous pouvez utiliser le même exemple que ci-dessus, en remplaçant l' Swingutilities.invokeLater avec le post approprié à un Handler.

3voto

CommonsWare Points 402670

Tout juste arrivé de répondre couvre pourquoi vous ne devriez pas faire ce que vous faites. Voici quelques solutions pour résoudre votre problème.

Ce thread est en train de faire quelque calcul dans le fond, si je ne pas le faire dans le thread que c'est fait dans le thread de l'INTERFACE utilisateur et l'utilisateur a trop longue attente.

Dump de votre propre fil et l'utiliser AsyncTask.

Ou de créer un nouveau fil de discussion lorsque vous en avez besoin.

Ou mettre en place votre thread travaillent à partir d'une file d'attente de travail (par exemple, LinkedBlockingQueue) plutôt que de redémarrer le fil.

3voto

Peter Lawrey Points 229686

Ce que vous devez faire est de créer un Runnable et de l’envelopper avec un nouveau thread à chaque fois que vous voulez exécuter le Runnable. Ce serait vraiment moche à faire mais vous pouvez envelopper un thread avec un autre thread pour exécuter le code à nouveau, mais le faire uniquement est que vous devez vraiment le faire.

1voto

alanlcode Points 2843

Il est comme vous l'avez dit, un thread ne peut pas être démarré plusieurs fois.

Straight from the horse's mouth: Java API Spec

Il n'est jamais juridiques pour démarrer un thread plus d'une fois. En particulier, un fil peut ne pas être redémarré une fois que c' a terminé son exécution.

Si vous avez besoin de re-exécuter tout ce qui se passe dans votre fil, vous devrez créer un nouveau thread et le lancer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X