Démarrage du fil:
1. Description de la différence entre start () et run ()
start (): sa fonction est de démarrer un nouveau thread et le nouveau thread exécutera la méthode Run () correspondante. start () ne peut pas être appelé à plusieurs reprises.
run (): run () peut être appelé à plusieurs reprises comme les méthodes de membres ordinaires. Si vous appelez Run () séparément, Run () sera exécuté dans le thread actuel et le nouveau fil ne sera pas démarré!
Ce qui suit est un code à expliquer.
classe Mythread étend Thread {public void run () {...}}; mythread mythread = new mythread (); MyThread.Start () démarre un nouveau thread et exécute la méthode run () dans le nouveau thread.
MyThread.Run () exécutera la méthode Run () directement dans le thread actuel et ne démarrera pas un nouveau thread pour run run ().
2. Exemple de la différence entre start () et run ()
Ci-dessous, démontrez la différence entre eux avec un exemple simple. Le code source est le suivant:
// Demo.java Code source Classe MyThread étend Thread {public mythread (String name) {super (name); } public void run () {System.out.println (thread.currentThread (). getName () + "est en cours d'exécution"); }}; public class Demo {public static void main (String [] args) {thread mythread = new mythread ("mythread"); System.out.println (Thread.currentThread (). GetName () + "Appelez MyThread.Run ()"); mythread.run (); System.out.println (Thread.currentThread (). GetName () + "Appelez MyThread.Start ()"); mythread.start (); }} Résultats en cours:
principal appel mythread.run () Main est RunningMain Call MyThread.start () Mythread est en cours d'exécution
Description des résultats:
(1) thread.currentThread (). GetName () est utilisé pour obtenir le nom de "Thread actuel". Le thread actuel fait référence au thread qui doit s'exécuter dans le CPU.
(2) Mythread.run () est appelé dans "Main Thread Main", et la méthode run () s'exécute directement sur "Main Thread Main".
(3) Mythread.start () commencera "Thread Mythread". Une fois "Thread Mythread" au démarrage, la méthode run () sera appelée; À l'heure actuelle, la méthode run () est exécutée sur "Thread Mythread".
Interruptions et terminaisons du fil
1. Interruption du fil: interruption ()
La fonction d'interruption () est d'interrompre le thread.
Ce fil est autorisé à s'interrompre; Lorsque d'autres threads appellent la méthode Interrupt () de ce thread, l'autorisation sera vérifiée via CheckAccess (). Cela peut lancer une exception de sécurité de sécurité.
Si le fil est dans un état de blocage: appeler attendre (), attendre (long) ou attendre (long, int) du fil en fera un état d'attente (blocage) ou appelle join (), join (long), join (long, int), sommeil (long), sommeil (long, int) du fil du fil fera également un état de blocage. Si le thread appelle sa méthode Interrupt () lors de son blocage, son "état d'interruption" sera effacé et une interruption de conception sera reçue. Par exemple, un thread entre dans un état de blocage via Wait (), et le fil est interrompu par Interrupt (); Appeler Interrupt () définira immédiatement le drapeau d'interruption du thread sur "VRAI", mais comme le thread est dans un état de blocage, "l'indicateur d'interruption" sera immédiatement effacé à "False", et une conception interrompue sera générée.
Si le thread est bloqué dans un sélecteur de sélecteur, alors lorsqu'il est interrompu par Interrupt (); L'indicateur d'interruption du thread est défini sur true et il sera renvoyé immédiatement de l'opération de sélection.
S'il n'appartient pas à la situation mentionnée ci-dessus, alors lorsque le thread est interrompu via Interrupt (), son indicateur d'interruption sera défini sur "VRAI".
L'interruption d'un "thread terminé" ne provoquera aucune opération.
2. Terminaison du fil
Les méthodes stop () et suspendre () dans le thread sont recommandées pour ne pas être utilisées en raison de leur insécurité inhérente!
Ensuite, je vais d'abord discuter de la méthode de terminaison des fils dans "Blocking State" et "Running State" respectivement, puis résumer une méthode générale.
1. Terminez le fil dans "l'état de blocage"
Habituellement, nous terminons un fil dans un "état de blocage" en "interrompant".
Lorsque le fil entre dans un état de blocage en raison de l'appel Sleep (), Wait (), Join () et d'autres méthodes; Si l'interruption () du thread est appelée pour le moment, la marque d'interruption du thread est définie sur true. Puisqu'il est dans un état de blocage, le drapeau d'interruption sera effacé et une exception InterruptedException est générée. Mettre InterruptedException jusqu'à ce qu'il soit approprié peut terminer le thread, sous la forme comme suit:
@OverridePublic void run () {try {while (true) {// Exécuter la tâche ...}} catch (interruptedException ie) {// en raison d'une exception InterruptedException, quittez la boucle while (true) et le thread se termine! }} Remarque: Lorsque la tâche est exécutée en continu dans While (true), lorsque le thread est dans un état de blocage, l'appel à interrompre () du thread génère une interruption InterruptedException. La capture interrompue est à l'extérieur tandis que (vrai), sortant ainsi de la boucle (vraie) while!
Remarque: La capture de l'interruption Exception est généralement placée à l'extérieur du corps de boucle (vraie), de sorte que la boucle while (vrai) sort lorsqu'une exception est générée. Sinon, si InterruptedException se trouve dans le corps de boucle (vrai) While, un traitement supplémentaire et de sortie est requis. Le formulaire est le suivant:
@OverridePublic void run () {while (true) {try {// exécuter la tâche ...} catch (interruptedException ie) {// InterruptedException est dans le corps de boucle while (true). // Lorsque le thread génère une exception InterruptedException, tandis que (true) peut continuer à fonctionner! Besoin de quitter manuellement la pause; }}} Remarque: L'exception d'interruption ci-dessus est capturée dans WHLE (true). Lorsqu'une exception InterruptedException est générée, elle n'est pas gérée par Catch et est toujours dans le corps de boucle (vraie) while; Pour quitter le corps de boucle while (vrai), une opération supplémentaire de la sortie du while (vrai) doit être effectuée.
2. Terminez le fil dans "l'état de course"
Habituellement, nous terminons un fil dans un "état de course" par "marquage". Parmi eux, il comprend "Interrupt Flag" et "Ajouter un drapeau supplémentaire".
(1) Terminez le fil à travers "Interrupteur d'interruption".
Le formulaire est le suivant:
@OverRidePublic void run () {while (! IsInterrupted ()) {// Exécuter la tâche ...}} Description: isInterrupted () détermine si l'interruption du drapeau du thread est vraie. Lorsque le thread est en cours d'exécution et que nous devons le terminer; La méthode Interrupt () du thread peut être appelée, et l'indicateur d'interruption du thread est marqué vrai, c'est-à-dire ISinterrupted () reviendra vrai. À ce stade, la boucle while sera sortie.
Remarque: Interrupt () ne termine pas les threads dans "Running State"! Il définit le drapeau d'interruption du fil pour True.
(2) passer "Ajouter des marques supplémentaires".
Le formulaire est le suivant:
Flag booléen volatile privé = true; protected void stoptask () {flag = false;} @ overRidepublic void run () {while (flag) {// exécuter la tâche ...}} Description: Il y a une balise de drapeau dans le thread, et sa valeur par défaut est vraie; Et nous fournissons StopTask () pour définir la balise de drapeau. Lorsque nous devons terminer le thread, l'appel de la méthode stoptask () du thread peut entraîner la sortie du thread de la boucle while.
Remarque: Le drapeau est défini comme le type volatil pour assurer la visibilité du drapeau. Autrement dit, après que d'autres threads modifient l'indicateur via StopTask (), ce thread peut voir la valeur de l'indicateur modifié.
Comprenez les méthodes de terminaison des threads dans "Blocking State" et "State Running", les threads de terminaison les plus courants sont les suivants:
@OverridePublic void run () {try {// 1. IsInterrupted () garantit que le fil sera terminé tant que l'interruption est marquée vraie. tandis que (! isInterrupted ()) {// Exécuter la tâche ...}} catch (InterruptedException ie) {// 2. L'exception InterruptedException garantit que lorsqu'une exception InterruptedException se produit, le fil est terminé. }} 3. Exemple de terminaison
Interrupt () est souvent utilisé pour terminer un thread "State Blocking". Reportez-vous à l'exemple suivant:
// Demo1.java Code source Classe Mythread étend Thread {public mythread (String name) {super (name); } @Override public void run () {try {int i = 0; while (! isInterrupted ()) {Thread.Sleep (100); // Dormez 100 ms I ++; System.out.println (thread.currentThread (). GetName () + "(" + this.getState () + ") Loop" + i); }} catch (InterruptedException e) {System.out.println (thread.currentThread (). getName () + "(" + this.getState () + ") Catch InterruptedException."); }}} classe publique Demo1 {public static void main (String [] args) {try {thread t1 = new mythread ("t1"); // Créer un nouveau System "Thread T1" System.out.println (t1.getName () + "(" + t1.getState () + ") est nouveau."); t1.start (); // Démarrer "Thread T1" System.out.println (t1.getName () + "(" + t1.getState () + ") est démarré."); // Le thread principal dort 300 ms, puis le thread principal envoie une instruction "interruption" à T1. Thread.Sleep (300); t1.interrupt (); System.out.println (t1.getName () + "(" + t1.getState () + ") est interrompu."); // Le fil principal dort pendant 300 ms, puis vérifie l'état de T1. Thread.Sleep (300); System.out.println (t1.getName () + "(" + t1.getState () + ") est interrompu maintenant."); } catch (InterruptedException e) {e.printStackTrace (); }}} Résultats en cours:
T1 (new) est nouveau.t1 (runnable) est démarré.t1 (Runnable) Loop 1T1 (Runnable) Loop 2T1 (timed_waiting) est interrompu.t1 (Runnable) Catch InterruptedException.t1 (terminé) est interrompu maintenant.
Description des résultats:
(1) Le thread principal principal crée du fil T1 via un nouveau mythread ("t1"), puis démarre le thread T1 via t1.start ().
(2) Après le démarrage de T1, son drapeau d'interruption sera vérifié en continu. Si le drapeau d'interruption est "faux", il dormira pendant 100 ms.
(3) Une fois que T1 a dormi, il passera au fil principal principal; Lorsque le thread principal s'exécute à nouveau, t1.interrupt () sera exécuté pour interrompre le thread T1. Une fois que T1 a reçu l'instruction d'interruption, le drapeau d'interruption de T1 sera défini sur "FALSE" et une interruption d'Exception sera lancée. Dans la méthode Run () de T1, il s'agit d'une exception prise en dehors du corps de la boucle pendant que; Par conséquent, la boucle est terminée.
Nous avons apporté une petite modification au résultat ci-dessus et déplacé le bloc de code qui a attiré l'exception InterruptedException dans la méthode run () vers le corps de boucle while.
// Demo2.java Code source Classe Mythread étend Thread {public mythread (String Name) {super (name); } @Override public void run () {int i = 0; while (! isInterrupted ()) {try {Thread.Sleep (100); // Sleep for 100ms} catch (InterruptedException ie) {System.out.println (thread.currentThread (). GetName () + "(" + this.getState () + ") Catch InterruptedException."); } i ++; System.out.println (thread.currentThread (). GetName () + "(" + this.getState () + ") Loop" + i); }}} public class Demo2 {public static void main (String [] args) {try {thread t1 = new mythread ("t1"); // Créer un nouveau System "Thread T1" System.out.println (t1.getName () + "(" + t1.getState () + ") est nouveau."); t1.start (); // Démarrer "Thread T1" System.out.println (t1.getName () + "(" + t1.getState () + ") est démarré."); // Le thread principal dort 300 ms, puis le thread principal envoie une instruction "interruption" à T1. Thread.Sleep (300); t1.interrupt (); System.out.println (t1.getName () + "(" + t1.getState () + ") est interrompu."); // Le fil principal dort pendant 300 ms, puis vérifie l'état de T1. Thread.Sleep (300); System.out.println (t1.getName () + "(" + t1.getState () + ") est interrompu maintenant."); } catch (InterruptedException e) {e.printStackTrace (); }}} Résultats en cours:
T1 (nouveau) est nouveau.t1 (runnable) est démarré.t1 (runnable) Loop 1T1 (runnable) Loop 2T1 (timed_waiting) est interrompu.t1 (runnable) Catch InterruptedException.T1 (Runnable) Loop 3T1 (Runnable) Loop 4T1 (Runnable) Loop 5T1 (Timed_Wait (Runnable) Boucle 6T1 (Runnable) Loop 7T1 (Runnable) Loop 8T1 (Runnable) Loop 9 ...
Description des résultats:
Le programme est entré dans une boucle morte!
Pourquoi cela se produit-il? En effet, T1 est interrompu par Interrupt () lorsqu'il «attend (bloquant) l'état». À l'heure actuelle, le drapeau d'interruption est effacé [qui est interrompu () retournera faux], et une exception InterruptedException est lancée [cette exception est capturée dans le corps de boucle while]. Par conséquent, T1 entrera naturellement dans un cercle vicieux.
Pour résoudre ce problème, nous devons un traitement supplémentaire pour quitter la boucle While lors de la capture de l'exception. Par exemple, l'ajout de pause ou de retour à Mythread Catch (InterruptedException) peut résoudre le problème.
Voici un exemple de thread qui met fin à un "état d'état" en "ajoutant des balises supplémentaires":
// Demo3.java Code de code source Mythread étend Thread {private volatile booléan drapeau = true; public void stopTask () {flag = false; } public mythread (String name) {super (name); } @Override public void run () {synchronisé (this) {try {int i = 0; while (flag) {thread.sleep (100); // Dormez 100 ms I ++; System.out.println (thread.currentThread (). GetName () + "(" + this.getState () + ") Loop" + i); }} catch (InterruptedException ie) {System.out.println (thread.currentThread (). getName () + "(" + this.getState () + ") Catch InterruptedException."); }}}} classe publique Demo3 {public static void main (String [] args) {try {mythread t1 = new mythread ("t1"); // Créer un nouveau System "Thread T1" System.out.println (t1.getName ()) + "(" + t1.getState () + ") est nouveau."); t1.start (); // Démarrer "Thread T1" System.out.println (t1.getName () + "(" + t1.getState () + ") est démarré."); // Le thread principal dort 300 ms, puis le thread principal envoie une instruction "interruption" à T1. Thread.Sleep (300); t1.stopTask (); System.out.println (t1.getName () + "(" + t1.getState () + ") est interrompu."); // Le fil principal dort pendant 300 ms, puis vérifie l'état de T1. Thread.Sleep (300); System.out.println (t1.getName () + "(" + t1.getState () + ") est interrompu maintenant."); } catch (InterruptedException e) {e.printStackTrace (); }}} Résultats en cours:
T1 (new) est nouveau.t1 (runnable) est démarré.t1 (Runnable) Loop 1T1 (Runnable) Loop 2T1 (timed_waiting) est interrompu.t1 (Runnable) Loop 3T1 (terminé) est interrompu maintenant.