Maison >Java >javaDidacticiel >Quatre façons d'arrêter le thread principal une fois toutes les tâches des sous-threads terminées
Le multi-threading est un point de connaissance très important en Java. Ici, l'éditeur résumera pour vous le multi-threading Java. J'espère que vous pourrez le maîtriser.
Méthode un Thread.sleep
Méthode deux ExecutorService
Méthode trois thread .join
Méthode 4 Thread.yield et Thread.activeCount
J'ai rencontré un tel scénario lors de l'écriture du code. Je dois observer l'état d'exécution de chaque sous-thread si aucun traitement n'est effectué, les autres sous-threads seront fermés après la méthode main
. est terminé, ce qui rend impossible l'observation de l'état d'exécution détaillé de tous les sous-threads, le thread principal doit donc attendre que tous les sous-threads aient fini de s'exécuter avant de s'arrêter. Dans le passé, l'approche la plus bâclée consistait à ajouter <.> à la fonction main
. Cependant, cette méthode n'est pas parfaite car elle nécessite de définir artificiellement le temps d'attente n'est pas la meilleure pratique, j'ai donc vérifié certaines informations et blogs, et voici quatre méthodes pour atteindre cet objectif Thread.sleep(time)
Méthode 1 Thread.sleep
public static void main(String[] args) throws InterruptedException{ for(int i=0; i<10; i++){ new Thread("subthread" + i){ @Override public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }.start(); } Thread.sleep(2000); System.out.println("main thread finished"); }Méthode 2 ExecutorService
subthread0finished subthread1finished subthread2finished subthread6finished subthread4finished subthread5finished subthread3finished subthread9finished subthread8finished subthread7finished main thread finished
ExecutorService
shutdown
Le résultat de l'exécution est :
public static void main(String[] args) { // 创建一个ExecutorService ExecutorService ex = Executors.newCachedThreadPool(); for(int i=0; i<10; i++){ // 添加 task ex.submit(new Thread("subthread" + i){ @Override public void run() { try{ Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }); } // 使用shutdown 会通知executorservice 停止添加其它task 它会等待所有子线程运行结束才退出Java进程 ex.shutdown(); System.out.println("main thread finished"); }
Cette méthode présente quelques défauts mineurs. .Nous pouvons voir à partir des informations de sortie que le thread principal termine réellement son exécution avant le thread enfant, donc cette méthode seule peut garantir que le sous-thread peut terminer son exécution avant la fin du programme, mais elle ne peut pas garantir que le thread principal le sera. exécuté une fois l'exécution du sous-thread terminée. Par conséquent, le code doit être modifié. Ajoutez un
pour définir un temps d'attente plus raisonnable et attendez que l'opération soit terminée.main thread finished pool-1-thread-3finished pool-1-thread-4finished pool-1-thread-2finished pool-1-thread-1finished pool-1-thread-5finished pool-1-thread-7finished pool-1-thread-8finished pool-1-thread-6finished pool-1-thread-9finished pool-1-thread-10finished
awaitTermination(time, timeunit)
Le résultat de l'opération :
public static void main(String[] args) { // 创建一个ExecutorService ExecutorService ex = Executors.newCachedThreadPool(); for(int i=0; i<10; i++){ // 添加 task ex.submit(new Thread("subthread" + i){ @Override public void run() { try{ Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }); } // 使用shutdown 会通知executorservice 停止添加其它task 它会等待所有子线程运行结束才退出Java进程 ex.shutdown(); try { // 设置等待时间等待子线程运行完毕 if(!ex.awaitTermination(2000, TimeUnit.MILLISECONDS)){ // 等待时间内子线程并未全部运行完毕就直接关闭 ex.shutdownNow(); } }catch(InterruptedException e){ ex.shutdownNow(); } System.out.println("main thread finished"); }
Vous pouvez voir que le contenu exécuté par le thread principal est affiché à la fin. Cette méthode doit définir le temps d'attente tout comme la méthode 1. Ce n'est pas une méthode parfaite.
pool-1-thread-1finished pool-1-thread-5finished pool-1-thread-4finished pool-1-thread-9finished pool-1-thread-8finished pool-1-thread-3finished pool-1-thread-2finished pool-1-thread-7finished pool-1-thread-6finished pool-1-thread-10finished main thread finishedMéthode trois thread.join
dans le thread thread.join
, il attendra que le sous-thread ait fini de s'exécuter avant de continuer. en continuant à exécuter main
Thread, le code est le suivant : main
某一个子线程.join
main
Résultat d'exécution :
public static void main(String[] args) throws InterruptedException{ List<Thread> list = new ArrayList<>(); for(int i=0; i<10; i++){ Thread t = new Thread("subthread" + i){ @Override public void run() { try{ Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }; list.add(t); t.start(); } for(Thread item : list){ item.join(); } System.out.println("main thread finished"); }
L'avantage d'utiliser cette méthode par rapport aux deux méthodes ci-dessus est qu'il Il n'est pas nécessaire de définir le temps d'attente.
subthread1finished subthread2finished subthread0finished subthread3finished subthread6finished subthread5finished subthread4finished subthread9finished subthread7finished subthread8finished main thread finishedméthode 4 Thread.yield et Thread.activeCountTout d'abord, expliquons les fonctions de ces deux méthodes
Mais cela ne signifie pas que le thread actuel ne sera plus exécuté. La méthode Thread.yield
renvoie le nombre de threads actifs dans. le groupe de threads correspondant au thread appelant actuel. Lors de la création d'un thread (nouveau Thread), le paramètre 放弃
fait référence à Créer le groupe de threads correspondant au thread. Si ce paramètre n'est pas précisé, le thread créé est le même groupe de threads. comme le fil qui a créé le fil. Le code est le suivant : CPU
Thread.activeCount
ThreadGroup
Résultat de l'exécution :
public static void main(String[] args) { // 关键参数 int defaultThreadNum = 2; for(int i=0; i<10 ;i++){ new Thread("subthread" + i){ @Override public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "finished"); }catch(InterruptedException e){ e.printStackTrace(); } } }.start(); } while(Thread.activeCount() > defaultThreadNum){ // 当活跃线程数大于设定的默认线程数的时候 主线程让步 Thread.yield(); } System.out.println("main thread finished"); }
Un point très clé est que
est défini sur 2. Certains les blogs le mettent à 1, mais 1 provoquera une boucle infinie et le thread principal ne pourra pas se fermer. La raison en est que tout le monde pense que le thread où se trouve le thread principal. Après avoir exclu les sous-threads du groupe, seul le thread principal est. gauche. En fait, ce n'est pas le cas. Par exemple, si nous exécutons le code suivant :subthread0finished subthread4finished subthread1finished subthread8finished subthread9finished subthread5finished subthread2finished subthread3finished subthread6finished subthread7finished main thread finished
defaultthreadnum
Sortie :
public static void main(String[] args) { Thread.currentThread().getThreadGroup().list(); }
Vous pouvez voir où se trouve le fil principal. est également un thread appelé
dans le groupe de threads, donc après avoir exclu tous les sous-threads, il reste encore 2 threads, donc le seuil de jugement de boucle (java.lang.ThreadGroup[name=main,maxpri=10] Thread[main,5,main] Thread[Monitor Ctrl-Break,5,main]) doit être défini sur 2.
Ceci La méthode n'a pas non plus besoin d'être définie. Temps d'attente.Monitor Ctrl-Break
defaultThreadNum
En résumé, si vous devez implémenter le thread principal pour qu'il s'exécute une fois que tous les sous-threads ont fini de s'exécuter, vous pouvez utiliser la méthode trois et la méthode quatre.
Recommandations associées :
Analyse complète du multi-threading Java Thread
php5 non -La différence entre thread-safe et thread-safe
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!