/ / Pourquoi mon entrée montre un thread s'exécutant après un autre thread, pas en même temps? - java, multithreading

Pourquoi mon entrée montre un thread s'exécutant après un autre thread, pas en même temps? - java, multithreading

J'ai recherché le concept d'un thread et j'ai vu qu'il s'agissait de faire exécuter du code dans deux processus en même temps. Voici mon code

public class Connor extends Thread{

public void run() {
for(int i=0; i< 10; i ++){
System.out.println("Hello " + i);
}

public static void main(String[] args){
Connor runner1 = new Connor();
Connor runner2 = new Connor();
runner1.start();
runner2.start();
}
}

Et ma sortie http://imgur.com/yAZqgal

Il semble que les deux fils commencent àen même temps (processus séparés, comme indiqué par les deux 0 en tête) mais l'un s'exécute (1-9) puis l'autre s'exécute (1-9). Ne supposent-ils pas qu'ils s'entrelacent également (1,1,2,2, ...) car les deux fils s'impriment sur la console. J'ai recherché et vu que le démarrage est la bonne méthode à utiliser car il indique à la classe de thread d'exécuter la méthode d'exécution dans un autre thread? Quelqu'un peut-il expliquer pourquoi je reçois cette sortie?

Réponses:

5 pour la réponse № 1

Dites que vous avez dix courses à faire et votrema sœur a dix courses à faire et vous n'avez qu'une seule voiture. Ramenez-vous la voiture après chaque course et changez de pilote? Bien sûr que non. Ce serait absurdement inefficace. Chaque thread a simplement besoin du flux de sortie. Il serait donc absurde de les entrelacer étroitement.


3 pour la réponse № 2

Votre code semble bien. Je suppose que vos threads ne tournent pas en parallèle simplement parce qu'ils se terminent trop rapidement. Modifiez la limite de boucle de 10 à 1000 et vous verrez l'effet.

Le fil de départ lui-même est relativement lourdopération. Votre code démarre le premier thread puis le second. Le premier thread une fois démarré se termine avant que le deuxième thread ait la chance de commencer à exécuter sa logique métier.


2 pour la réponse № 3

En cas de filetage multiple, il n'y a aucune garantiequel thread est alloué pour quel temps exécuter par le processeur et dans ce cas le résultat est imprévisible et générera une sortie différente pour chaque exécution.

Si vous recherchez la sortie souhaitée, vous avez besoin d'un bloc de synchronisation. en utilisant wait et notify vous pouvez y parvenir facilement.

Veuillez consulter la leçon ci-dessous directement de Site officiel d'Oracle:

Remarque: wait Et notify doit être appelé à l'intérieur du synchronized bloc et peut faire appel au même objet sur lequel il est synchronisé.

Exemple de code: (lire les commentaires en ligne)

public class Connor extends Thread {

private static Connor runner1 = new Connor();
private static Connor runner2 = new Connor();

public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Hello " + i);

// wake up another thread to come out from wait state
if (runner1 == this) {
// wake up runner2
synchronized (runner2) {
runner2.notify();
}
} else {
// wake up runner1
synchronized (runner1) {
runner1.notify();
}
}

synchronized (this) {
try {
// say current thread to wait until notify by another thread
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) {
runner1.start();
runner2.start();
}
}

sortie:

Hello 0
Hello 0
Hello 1
Hello 1
Hello 2
Hello 2
Hello 3
Hello 3
Hello 4
Hello 4
Hello 5
Hello 5
Hello 6
Hello 6
Hello 7
Hello 7
Hello 8
Hello 8
Hello 9
Hello 9

0 pour la réponse № 4

Pourquoi mon entrée montre un thread s'exécutant après un autre thread, pas en même temps?

L'explication générale est que la planification des threads est imprévisible. Entrelacement mai arriver ... ou Peut-être pas. C'est fondamental pour le filetage Java. (Et en effet au filetage dans la plupart des autres langues.)

Si vous avez besoin d'une exécution de thread pour entrelacer dans unmanière entièrement prévisible, vous devez implémenter une sorte de mécanisme de poignée de main, où un thread attend qu'un autre fasse quelque chose, et continue. Mais cela est compliqué et va généralement à l'encontre du but de l'utilisation du filetage.

FWIW: La réponse de @Braj montre comment vous pouvez implémenter un entrelacement strict. Cependant, notez que cela signifie effectivement qu'un seul thread va s'exécuter à la fois. En outre, l'attente / notification va entraîner beaucoup de travail pour le thread planificateur ... certains que l'application s'exécutera beaucoup plus lentement que si vous veniez de faire le travail sur un thread.


Dans cet exemple particulier, deux problèmes se combinent pour rendre improbable tout entrelacement à court terme:

  1. La création d'un nouveau thread natif en Java estrelativement coûteux, car cela implique généralement de demander un bloc de mémoire au système d'exploitation pour héberger la pile de threads. Cela implique à son tour que le système d'exploitation "déconne" avec les tables de pages, la remise à zéro d'un bloc de mémoire, etc.

  2. La planification des threads natifs est implémentée par lesystème d'exploitation, et il fonctionne à un niveau assez grossier ... parce que c'est le moyen le plus efficace de fonctionner du point de vue d'une application typique. (Changer de "contexte" de thread dans une machine de classe PC est une opération relativement coûteuse, et le planificateur de thread lui-même a potentiellement du travail à faire.)

Dans votre exemple, il est probable que le premier thread puisse dire "bonjour" dix fois avant que le deuxième thread ne soit prêt à être planifié.