Pourquoi run () pas immédiatement appelé au moment du départ () a appelé un objet thread en java

StackOverflow https://stackoverflow.com/questions/2690207

  •  01-10-2019
  •  | 
  •  

Question

Ou est-ce?
J'ai un objet de fil de:

Thread myThread = new Thread(pObject);

Où PObject est un objet d'une classe qui implémente l'interface Runnable puis j'ai la méthode de démarrage appelée sur l'objet de fil comme ceci:

myThread.start();

Maintenant, je crois comprendre que lorsque le démarrage () est appelée, la machine virtuelle Java implicitement (et immédiatement) appelle la méthode run () qui peut être surchargée (comme dans mon cas)

Cependant, dans mon cas, il semble que la méthode start () n'est pas appelé immédiatement (comme on le souhaite), mais jusqu'à ce que les autres déclarations / méthodes sont complétées de la c.-à-bloc d'appel si j'avais une méthode après le début () appel comme ceci:

myThread.start();
doSomethingElse();

doSomthingElse () est exécuté avant que la méthode run () est exécuté du tout.
Peut-être que je me trompe avec la prémisse initiale run () est toujours appelé juste après le début () est appelée. Aide s'il vous plaît! Le nouveau souhaité est de faire courir l'exécution () juste après le démarrage (). Merci.

Était-ce utile?

La solution

  

Maintenant, je crois comprendre que lorsque le démarrage () est appelée, la machine virtuelle Java implicitement (et immédiatement) appelle la méthode run () ...

C'est incorrect. Il ne remet implicitement run(), mais l'appel ne se produit pas nécessairement immédiatement.

La réalité est que le nouveau fil devient disponible pour être programmé à un moment donné dans le temps après l'appel start() est fait. La programmation réelle est à l'ordonnanceur natif. Il pourrait se produire immédiatement, ou le fil parent pourrait se poursuivre pendant une période avant que le fil de l'enfant est prévue.

Pour forcer votre fil à commencer à courir immédiatement (ou pour être plus précis, de commencer à courir avant doSomethingElse()), vous devez faire une synchronisation explicite; par exemple. quelque chose comme ceci:

    java.util.concurrent.CountDownLatch latch = new CountdownLatch(1);
    new Thread(new MyRunnable(latch)).start();
    latch.await(); // waits until released by the child thread.
    doSomethingElse();

class MyRunnable implements Runnable {
    private CountDownLatch latch;
    MyRunnable (CountDownLatch latch) { this.latch = latch; }
    public void run() {
        doSomeStuff();
        latch.countDown(); // releases the parent thread
        doSomeMoreStuff();
    }
    ...
}

Il existe d'autres façons de mettre en œuvre la synchronisation en utilisant les classes Java ou simultanéité de mutex / wait / notify primitives 1 . Mais la synchronisation explicite entre les deux threads est la seule façon de garantir le comportement dont vous avez besoin.

Notez que l'appel doSomething() dans le thread enfant se termine avant le thread parent est libéré, mais nous pouvons rien dire de l'ordre d'exécution des doSomethingElese() et doSomeMoreStuff(). (On pourrait courir avant l'autre et vice versa, ou ils peuvent fonctionner en parallèle.)


1 - L'utilisation wait / notify n'est pas recommandé, mais il est peut-être votre seule option si les API d'accès concurrentiel ne sont pas disponibles; par exemple. sur Java ME.

Autres conseils

Um ... la méthode run() fonctionnera dans un autre thread . Que, par définition, signifie que vous ne pouvez pas faire tout hypothèses sur avant ou après quoi les déclarations dans le thread courant il exécutera, à moins que vous les synchroniser explicitement.

run() est la première chose dans votre code que le nouveau thread fait, mais il y a un travail de mise en place que le nouveau fil fait en premier lieu, et il n'y a aucune garantie que le nouveau thread en fait une quantité importante de travail avant la thread d'origine se poursuit à l'appel doSomethingElse().

Vous avez raison de penser qu'il n'y a aucune garantie ici. Faire des hypothèses sur le comportement du code multithread est la source de beaucoup de douleur - essayez de ne pas le faire

Lorsque vous appelez myThread.start(), votre fil devient disponible pour l'exécution. Que ce sera effectivement gagner CPU, et pour combien de temps - il est le planificateur du système d'exploitation. En fait, votre run() peut obtenir le contrôle immédiatement, mais la perdre avant de pouvoir faire quoi que ce soit, vous pouvez remarquer. La seule façon de faire en sorte que votre fil exécute ce que vous avez besoin avant doSomethingElse() est d'utiliser la synchronisation explicite.

Vous avez commencé un nouveau fil. Ce fil fonctionne en parallèle au fil qui a commencé si l'ordre pourrait être:

pObject.run();
doSomethingElse();

ou

doSomethingElse();
pObject.run();

ou, plus probablement, il y aura un certain croisement. pObject.run() peut courir au milieu de doSomethingElse() ou vice versa, ou on commencera avant les autres finitions et ainsi de suite. Il est important de comprendre et de comprendre ce qu'on entend par une opération atomique ou vous vous retrouverez avec quelques bugs vraiment difficiles à trouver.

Il est encore plus compliqué si deux ou plusieurs threads d'accéder aux mêmes variables. La valeur d'un peut jamais être mis à jour dans un thread dans certaines circonstances.

Je vous suggère fortement:

  1. ne pas faire de votre multi-thread programme à moins que vous absolument besoin de; et

  2. Si vous le faites, acheter et lire du début à la Brian Goetz Java dans la pratique Concurrency.

appelant la méthode de démarrage sur un objet de discussion ne peut pas faire la jvm invoquer la méthode run () immidiately, elle rend plutôt le fil un runnable et prêt pour l'exécution, dans ce cas, le thread parent premier exécute son code et passe ensuite le contrôle au fil de l'enfant, si tu veux le fil de l'enfant à exécuter avant le code de thread parent est exécuté utiliser la méthode chileThreadObject.join () dans le thread parent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top