Four ways to shut down the main thread after all sub-thread tasks are completed
Multi-threading is a very important knowledge point in Java. Here I will summarize Java Thread multi-threading for you. It is very useful. I hope you can master it.
Method one Thread.sleep
Method two ExecutorService
Method three thread .join
- ##Method 4 Thread.yield and Thread.activeCount
##I encountered such a scenario when writing code. It is necessary to observe the running status of each sub-thread. If no processing is performed, other sub-threads will be closed after the
main method is completed. , it is impossible to observe the detailed running status of all sub-threads, so the main thread needs to wait for all sub-threads to finish running before shutting down. In the past, a more careless approach was to add Thread in the
main function. sleep(time)
However, this method is not perfect, because it requires artificial setting of waiting time, which is not the best practice, so I checked some information and blogs, and here are four methods to achieve this purpose.Method 1 Thread.sleep
This should be the most common method. Although it is not the best practice, it can barely meet the needs.
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"); }
Running results:
subthread0finished subthread1finished subthread2finished subthread6finished subthread4finished subthread5finished subthread3finished subthread9finished subthread8finished subthread7finished main thread finished
Method 2 ExecutorService
can be implemented using a thread pool. Commonly used thread pool objects are implementations of the
ExecutorService interface, which provides shutdown
and other methods. Ensure that the Java process exits normally after the currently submitted task is finished running on the child thread. <pre class='brush:php;toolbar:false;'>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");
}</pre>
The running result is:
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
This method has some minor flaws, we can judge from the output information It can be seen that the main thread actually finishes running before the sub-thread, so this method can only ensure that the sub-thread can finish running before the program exits, but it cannot guarantee that the main thread will be executed after the sub-thread finishes running. So the code still needs to be changed, Add a
awaitTermination(time, timeunit) Set a more reasonable waiting time and wait for the sub-thread to finish running.<pre class='brush:php;toolbar:false;'>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");
}</pre>
Running results:
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 finished
You can see the main The content executed by the thread is output at the end. This method requires setting the waiting time just like method one, which is not a perfect method.
Method three thread.join
thread. join means that the thread running this code will be in a suspended state, waiting for the thread calling this method (here this thread) to finish running before continuing to run. In the following example, the child threads are all in main
is created above the thread, so when running a certain sub-thread.join
in the main
thread, it will wait for the sub-thread to finish running before continuing to run the main
thread , the code is as follows: <pre class='brush:php;toolbar:false;'>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");
}</pre>
Run result:
subthread1finished subthread2finished subthread0finished subthread3finished subthread6finished subthread5finished subthread4finished subthread9finished subthread7finished subthread8finished main thread finished
The advantage of using this method compared to the above two methods is that there is no need to set the waiting time.
Method 4 Thread.yield and Thread.activeCount
First explain the functions of these two methods,
Thread.yield In layman's terms, it means giving in. The current thread that calls this method gives up
and occupies it by itselfCPU
. However, it does not mean that the current thread will no longer be executed. The Thread.activeCount
method returns the number of active threads in the thread group corresponding to the current calling thread. When creating a thread (new Thread) The ThreadGroup
parameter refers to the thread group corresponding to the created thread. If this parameter is not specified, then the created thread is the same thread group as the thread that created this thread. The code is as follows :<pre class='brush:php;toolbar:false;'>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");
}</pre>
Running result:
subthread0finished subthread4finished subthread1finished subthread8finished subthread9finished subthread5finished subthread2finished subthread3finished subthread6finished subthread7finished main thread finished
One very key point is this
defaultthreadnum is set to 2. Some blogs set it to 1, but 1 will This leads to an infinite loop and the main thread cannot exit. The reason is that everyone thinks that after excluding the sub-threads in the thread group where the main thread is located, only the main thread is left. In fact, this is not the case. For example, if we run the following code: <pre class='brush:php;toolbar:false;'>public static void main(String[] args) {
Thread.currentThread().getThreadGroup().list();
}</pre>
Output:
java.lang.ThreadGroup[name=main,maxpri=10] Thread[main,5,main] Thread[Monitor Ctrl-Break,5,main]
You can see that there is another thread called
Monitor Ctrl-Break in the thread group where the main thread is located. Therefore, after excluding all child threads, there are still 2 threads left, so the loop The judgment threshold (defaultThreadNum
) needs to be set to 2. This method also does not need to set the waiting time.
In summary, if you need to implement the main thread in all sub-threads You can use method three and method four before running again.
Related recommendations:
The above is the detailed content of Four ways to shut down the main thread after all sub-thread tasks are completed. For more information, please follow other related articles on the PHP Chinese website!

JVMmanagesgarbagecollectionacrossplatformseffectivelybyusingagenerationalapproachandadaptingtoOSandhardwaredifferences.ItemploysvariouscollectorslikeSerial,Parallel,CMS,andG1,eachsuitedfordifferentscenarios.Performancecanbetunedwithflagslike-XX:NewRa

Java code can run on different operating systems without modification, because Java's "write once, run everywhere" philosophy is implemented by Java virtual machine (JVM). As the intermediary between the compiled Java bytecode and the operating system, the JVM translates the bytecode into specific machine instructions to ensure that the program can run independently on any platform with JVM installed.

The compilation and execution of Java programs achieve platform independence through bytecode and JVM. 1) Write Java source code and compile it into bytecode. 2) Use JVM to execute bytecode on any platform to ensure the code runs across platforms.

Java performance is closely related to hardware architecture, and understanding this relationship can significantly improve programming capabilities. 1) The JVM converts Java bytecode into machine instructions through JIT compilation, which is affected by the CPU architecture. 2) Memory management and garbage collection are affected by RAM and memory bus speed. 3) Cache and branch prediction optimize Java code execution. 4) Multi-threading and parallel processing improve performance on multi-core systems.

Using native libraries will destroy Java's platform independence, because these libraries need to be compiled separately for each operating system. 1) The native library interacts with Java through JNI, providing functions that cannot be directly implemented by Java. 2) Using native libraries increases project complexity and requires managing library files for different platforms. 3) Although native libraries can improve performance, they should be used with caution and conducted cross-platform testing.

JVM handles operating system API differences through JavaNativeInterface (JNI) and Java standard library: 1. JNI allows Java code to call local code and directly interact with the operating system API. 2. The Java standard library provides a unified API, which is internally mapped to different operating system APIs to ensure that the code runs across platforms.

modularitydoesnotdirectlyaffectJava'splatformindependence.Java'splatformindependenceismaintainedbytheJVM,butmodularityinfluencesapplicationstructureandmanagement,indirectlyimpactingplatformindependence.1)Deploymentanddistributionbecomemoreefficientwi

BytecodeinJavaistheintermediaterepresentationthatenablesplatformindependence.1)Javacodeiscompiledintobytecodestoredin.classfiles.2)TheJVMinterpretsorcompilesthisbytecodeintomachinecodeatruntime,allowingthesamebytecodetorunonanydevicewithaJVM,thusfulf


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

SublimeText3 Chinese version
Chinese version, very easy to use

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

EditPlus Chinese cracked version
Small size, syntax highlighting, does not support code prompt function

SublimeText3 Linux new version
SublimeText3 Linux latest version

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.
