Home > Java > javaTutorial > body text

Four ways to shut down the main thread after all sub-thread tasks are completed

坏嘻嘻
Release: 2018-09-14 16:27:43
Original
4149 people have browsed it

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");
    }
Copy after login

Running results:

subthread0finished
subthread1finished
subthread2finished
subthread6finished
subthread4finished
subthread5finished
subthread3finished
subthread9finished
subthread8finished
subthread7finished
main thread finished
Copy after login

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. <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&lt;10; i++){ // 添加 task ex.submit(new Thread(&quot;subthread&quot; + i){ @Override public void run() { try{ Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + &quot;finished&quot;); }catch(InterruptedException e){ e.printStackTrace(); } } }); } // 使用shutdown 会通知executorservice 停止添加其它task 它会等待所有子线程运行结束才退出Java进程 ex.shutdown(); System.out.println(&quot;main thread finished&quot;); }</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
Copy after login

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&lt;10; i++){ // 添加 task ex.submit(new Thread(&quot;subthread&quot; + i){ @Override public void run() { try{ Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + &quot;finished&quot;); }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(&quot;main thread finished&quot;); }</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
Copy after login

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&lt;Thread&gt; list = new ArrayList&lt;&gt;(); for(int i=0; i&lt;10; i++){ Thread t = new Thread(&quot;subthread&quot; + i){ @Override public void run() { try{ Thread.sleep(3000); System.out.println(Thread.currentThread().getName() + &quot;finished&quot;); }catch(InterruptedException e){ e.printStackTrace(); } } }; list.add(t); t.start(); } for(Thread item : list){ item.join(); } System.out.println(&quot;main thread finished&quot;); }</pre><div class="contentsignin">Copy after login</div></div>Run result:

subthread1finished
subthread2finished
subthread0finished
subthread3finished
subthread6finished
subthread5finished
subthread4finished
subthread9finished
subthread7finished
subthread8finished
main thread finished
Copy after login

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 :<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&lt;10 ;i++){ new Thread(&quot;subthread&quot; + i){ @Override public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + &quot;finished&quot;); }catch(InterruptedException e){ e.printStackTrace(); } } }.start(); } while(Thread.activeCount() &gt; defaultThreadNum){ // 当活跃线程数大于设定的默认线程数的时候 主线程让步 Thread.yield(); } System.out.println(&quot;main thread finished&quot;); }</pre><div class="contentsignin">Copy after login</div></div>Running result:

subthread0finished
subthread4finished
subthread1finished
subthread8finished
subthread9finished
subthread5finished
subthread2finished
subthread3finished
subthread6finished
subthread7finished
main thread finished
Copy after login

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]
Copy after login

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:


Java Thread multi-thread comprehensive analysis

php5 non -The difference between thread-safe and thread-safe

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!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template