Pourquoi appelons-nous la méthode start()
de l'objet thread qui appelle à son tour la méthode run()
? Pourquoi ne pas appeler directement la méthode run()
?
[...] pourquoi ne pas appeler directement la méthode run ()?
La méthode run()
est juste une méthode ordinaire (remplacée par you). Comme avec toute autre méthode ordinaire et l'appeler directement, le thread current exécutera run()
.
Toute la magie se passe à l'intérieur de start()
. La méthode start()
amène la machine virtuelle Java à générer un nouveau thread et à exécuter le thread nouvellement généré pour exécuter run()
.
Si vous appelez directement la méthode run (), son corps est exécuté dans le contexte du thread actuel. Lorsque vous appelez la méthode start()
, un nouveau thread est créé et la méthode run()
est exécutée dans ce nouveau thread.
Même si, par programme, nous ne créons pas de thread, O.S créera un thread par défaut pour exécuter son code avec CPU.
L'appel direct de la méthode run la fera exécuter dans le thread principal donné par O.S.
Mais l’intention de créer une classe de thread est de s’assurer que la méthode run s’exécute dans un autre thread. À moins que le gestionnaire de threads d'O.S ne crée un thread, votre méthode d'exécution ne sera pas exécutée dans un thread séparé. Pour demander à O.S de créer le thread séparé, vous devez appeler la méthode start () qui enverra une demande à O.S pour créer un thread. Une fois qu'O.S a créé un thread, il appellera automatiquement la méthode d'exécution de votre classe de thread dans le contexte de thread nouvellement créé. Et par conséquent, votre objectif de créer un thread séparé et d'exécuter votre méthode d'exécution dans un thread séparé sera servi.
Si vous appelez directement la méthode d’exécution, c’est comme si O.S ne créait aucun thread pour vous et que le thread principal par défaut exécutera votre méthode d’exécution. Pas la peine de créer une classe de threads séparée pour ça!
J'espère que je suis clair. Faites-moi savoir si vous avez besoin de plus d'explications pour répondre à votre question.
Remarque: Bien que les livres indiquent que JVM crée des threads, JVM devra en interne envoyer une demande au pilote de gestionnaire de threads de la couche O.S pour créer un nouveau thread dans son pool de threads. C'est pourquoi j'utilise davantage le terme O.S que la JVM.
Pourquoi appelons-nous la méthode start () de l'objet thread qui appelle à son tour méthode run ()
Non ce n'est pas. start()
appelle le système d'exploitation qui lance un nouveau thread qui (pour simplifier considérablement) appelle la méthode run()
. Pendant ce temps, la méthode start()
est déjà revenue à son appelant. Ils ne sont pas équivalents.
Runnable
est juste une interface. Une classe implémentant Runnable
n'a rien de spécial, elle a juste une méthode run
.
Thread#start
est une méthode mise en œuvre de manière native qui crée un thread distinct et appelle la méthode Thread
de run
, en exécutant le code dans le nouveau thread.
Thread
implémente Runnable
. Le code pour run
ressemble à ceci:
@Override
public void run() {
if (target != null) {
target.run();
}
}
Si l'instance Thread
a été créée en passant une Runnable
au constructeur Thread
, la méthode Runnable
's run
est appelée.
Sinon, les classes étendues Thread
doivent remplacer la méthode run
pour que start
puisse fonctionner.
L'appel de run
sur Thread
ne crée PAS de nouveau thread.
Si un thread a été instancié mais pas encore démarré, on dit qu'il est dans nouvel état .
Sauf si une méthode start () est invoquée sur l'instance du thread, celle-ci ne sera pas dite en vie.
Si vous n'appelez pas de méthode start () sur le thread d'instance de thread nouvellement créé, il n'est pas considéré comme étant actif.
Si la méthode start () n'est pas appelée et que la méthode run () est directement appelée sur l'occurrence de Thread, le code contenu dans la méthode run () ne s'exécutera pas dans un nouveau thread séparé, mais démarrera dans le thread existant. .
VOIR LE PROBLÈME PAR EXEMPLE
class Multi extends Thread{
public void run(){
for(int i=1;i<5;i++){
try{Thread.sleep(500);}catch(InterruptedException e){System.out.println(e);}
System.out.println(i);
}
}
public static void main(String args[]){
Multi t1=new Multi();
Multi t2=new Multi();
t1.run();
t2.run();
}
}
Output:1
2
3
4
5
1
2
3
4
5
Comme vous pouvez le constater dans le programme ci-dessus, il n'y a pas de changement de contexte car ici, t1 et t2 seront traités comme des objets normaux, et non des objets thread.
Je suppose que vous parlez de démarrer un fil. Si c'est le cas, la raison pour laquelle vous n'invoquez pas directement la méthode d'exécution est que vous appelez alors la méthode sans démarrer le thread.
C'est dû à la conception du multithreading en Java.
L'appel de start ()
démarrera un nouveau thread et l'appel de la méthode run()
ne démarrera pas un nouveau thread.
Si vous appelez la méthode start()
sur un thread, Java Virtual Machine appellera la méthode run () et deux threads s'exécuteront simultanément: l'implémentation Current et autre thread ou Runnable.
Regardez le code source de la méthode start()
dans Classe de thread
/**
* Causes this thread to begin execution; the Java Virtual Machine
* calls the <code>run</code> method of this thread.
* <p>
* The result is that two threads are running concurrently: the
* current thread (which returns from the call to the
* <code>start</code> method) and the other thread (which executes its
* <code>run</code> method).
* <p>
* It is never legal to start a thread more than once.
* In particular, a thread may not be restarted once it has completed
* execution.
*
* @exception IllegalThreadStateException if the thread was already
* started.
* @see #run()
* @see #stop()
*/
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
start0();
if (stopBeforeStart) {
stop0(throwableFromStop);
}
}
private native void start0();
Dans le code ci-dessus, vous ne pouvez pas voir l'invocation de la méthode run()
.
private native void start0()
est responsable de l'appel de la méthode run()
. JVM crée un thread natif correspondant au thread Java et appelle la méthode run()
.
Reportez-vous à cette question pour le code source des méthodes natives:
Où trouver le code source pour les méthodes natives Java.lang?
Lorsque nous utilisons la méthode start, un nouveau thread est créé, puis le code de la méthode run est exécuté pour chaque nouveau thread.
L'utilisation de la méthode start crée deux piles pour chaque thread, pile et pile native.
Mais la méthode Run
appelle simplement execute
le code de la méthode run
de manière séquentielle, car l'appel de la méthode d'exécution ne crée pas de piles différentes.
Exemple
import Java.util.concurrent.TimeUnit;
public class thread implements Runnable{
/**
* @param args
*/
public static void main(String[] args) {
Thread gg=new Thread(new thread());
Thread gg1=new Thread(new thread());
gg.run();
gg1.start();
/*gg.start();
gg1.start();*/
}
@Override
public void run() {
for(int i=0;i<5;i++)
{
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Hello..." + i);
}
}
}
Les méthodes start()
et run()
sont utilisées pour exécuter un thread. La méthode run()
est juste une méthode ordinaire; elle est substituée par l'utilisateur et sera appelée sur le thread en cours . La méthode start()
exécute la méthode run()
indirectement et crée nouveau fil.
Si nous voulons, nous pouvons appeler la méthode run()
, mais si nous appelons la méthode run, celle-ci sera exécutée comme une méthode Java normale. Alors que nous l'appelons start(
), JVM
crée un nouveau thread et la méthode run sera exécutée sur ce thread.