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
##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
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
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. <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;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><div class="contentsignin">Copy after login</div></div>
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.<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;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><div class="contentsignin">Copy after login</div></div>
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: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;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><div class="contentsignin">Copy after login</div></div>
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
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 :<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;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><div class="contentsignin">Copy after login</div></div>
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: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">public static void main(String[] args) {
Thread.currentThread().getThreadGroup().list();
}</pre><div class="contentsignin">Copy after login</div></div>
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!