Java Multithreading--Let the main thread wait for all child threads to finish executing _java

Source: Internet
Author: User
Tags current time

My friend asked me to help you write a program to import data from a text document into an Oracle database, there is no technical difficulty, the document format is fixed as long as the corresponding database in the field parsing on the line, the key is performance.

The volume of data is very large millions records, so considering to use multithreading concurrent execution, in the process of writing and encountered problems, I would like to count all the child processes complete the total time elapsed, the first child process before the creation of a record of the current times with System.currenttimemillis () When the current time is recorded after the end of the last subprocess, the two time difference is total, the code is as follows

Long Tstart = System.currenttimemillis (); 
System.out.println (Thread.CurrentThread (). GetName () + start);//print start tag for 
(int II = 0; II < threadnum; ii++) {//Open th Readnum thread 
Runnable r = new Runnable () { 
@Override public 
void Run () { 
System.out.println ( Thread.CurrentThread (). GetName () + "start"); 
Do something ... 
System.out.println (Thread.CurrentThread (). GetName () + "end."); 
} 
Thread t = new Thread (r); 
T.start (); 
} 
System.out.println (Thread.CurrentThread (). GetName () + "end."); /print end tag 
long tend = system.currenttimemillis (); 
SYSTEM.OUT.PRINTLN ("Total When:" + (Tend-tstart) + "millions"); 

The result is that almost immediately after the end of the for Loop, the statement that the main thread prints in total is executed. The reason is that all of the child threads are executed concurrently and they run with the main thread running, which leads to the problem of how the title "Let the main thread wait for all child threads to finish". Try to add t.join () after each child thread starts, and the result is that all threads execute sequentially, which loses the meaning of concurrency, obviously not what I want.

Google on the internet for a long time did not find a solution, do not people have encountered this kind of demand? Or is the problem too simple? No resistance had to find a way ...

Finally, my solution is to customize a Importthread class to inherit from Java.lang.Thread, overload the Run () method, and save all generated threads with a list property, so that if you decide whether the list is empty, you know if there are any child threads that are not executed. The class code is as follows:

public class Importthread extends Thread { 
private static list<thread> runningthreads = new Arraylist<thread > (); 
Public Importthread () { 
} 
@Override public 
void Run () { 
regist (this);//Registration 
at the start of a thread System.out.println (Thread.CurrentThread (). GetName () + "start ...");//print start tag 
//do something ... 
Unregist (this), or when the thread ends, cancels 
the registration System.out.println (Thread.CurrentThread (). GetName () + "end."); /print end tag 
} public 
void Regist (Thread t) { 
  synchronized (runningthreads) {  
    runningthreads.add (t); 
  } 
} 
public void Unregist (Thread t) { 
  synchronized (runningthreads) {  
    runningthreads.remove (t); 
  } 
} 
public static Boolean hasthreadrunning () {return 
(runningthreads.size () > 0); By determining whether the runningthreads is empty, you can know if the thread has not finished executing 
} 
 

Code in main thread:

Long Tstart = System.currenttimemillis (); 
System.out.println (Thread.CurrentThread (). GetName () + start);//print start tag for 
(int II = 0; II < threadnum; ii++) {//Open th Readnum threads thread 
t = new Importthread (); 
T.start (); 
} 
while (true) {//wait for all child threads to finish executing 
if (! Importthread.hasthreadrunning ()) {break 
; 
} 
Thread.Sleep (+); 
} 
System.out.println (Thread.CurrentThread (). GetName () + "end."); /print end tag 
long tend = system.currenttimemillis (); 
SYSTEM.OUT.PRINTLN ("Total When:" + (Tend-tstart) + "millions"); 

The results of printing are:

Main start
Thread-1 start ...
Thread-5 start ...
Thread-0 start ...
Thread-2 start ...
Thread-3 start ...
Thread-4 start ...
Thread-5 end.
Thread-4 end.
Thread-2 end.
Thread-0 end.
Thread-3 end.
Thread-1 end.
Main end.

Total spents: 20860millions

You can see that the main thread is not executed until all child threads have been completed.

=================================================================================================

The above method has a hidden danger: If thread 1 starts and ends, and the other thread does not start at this time Runningthreads's size is also 0, the main thread will assume that all threads are finished. The workaround is to replace the list type with a counter of a runningthreads type, and the value of the counter should be set before the thread is created.

Mycountdown class

  public class Mycountdown { 
private int count; 
public Mycountdown (int count) { 
This.count = count; 
} 
Public synchronized void Countdown () { 
count--; 
} 
Public synchronized Boolean Hasnext () {return 
(Count > 0); 
} 
public int GetCount () {return 
count; 
} 
public void SetCount (int count) { 
This.count = count; 
} 
} 

Importthread class

 public class Importthread extends Thread { 
private mycountdown C; 
Public Importthread (Mycountdown c) { 
this.c = c; 
} 
@Override public 
Void Run () { 
System.out.println (Thread.CurrentThread (). GetName () + "start ...");//print start tag 
/ /do something 
C.countdown ()//timer minus 1 
System.out.println (Thread.CurrentThread (). GetName () + "end." Also "+ c.getcount () +" threads ");//print end tag 
} 
} 

In the main thread

System.out.println (Thread.CurrentThread (). GetName () + "start")//Print start tag 
mycountdown c = new Mycountdown (threadnum) ;//Initialize countdown for 
(int II = 0; II < threadnum ii++) {//Open threadnum thread 
t = new Importthread (c); 
T.start (); 
} 
while (true) {//wait for all child threads to complete the 
if (!c.hasnext ()) break; 
} 
System.out.println (Thread.CurrentThread (). GetName () + "end."); /Print end tag 

Print results:

Main start
Thread-2 start ...
Thread-1 start ...
Thread-0 start ...
Thread-3 start ...
Thread-5 start ...
Thread-4 start ...
Thread-5 end. There are 5 other threads
Thread-1 end. There are 4 other threads
Thread-4 end. There are 3 other threads
Thread-2 end. There are 2 other threads
Thread-3 end. There are 1 other threads
Thread-0 end. There are 0 other threads
Main end.

A simpler approach: use Java.util.concurrent.CountDownLatch instead of mycountdown, substituting the await () method instead of while (true) {...}

Importthread class

public class Importthread extends Thread { 
private countdownlatch threadssignal; 
Public Importthread (Countdownlatch threadssignal) { 
this.threadssignal = threadssignal; 
} 
@Override public 
Void Run () { 
System.out.println (Thread.CurrentThread (). GetName () + "start ..."); 
Do somethings 
Threadssignal.countdown ()//thread ends up with a counter minus 1 
System.out.println (Thread.CurrentThread (). GetName () + "end." Also "+ threadssignal.getcount () +" threads "); 
} 
 

In the main thread

Countdownlatch threadsignal = new Countdownlatch (threadnum);//Initialize countdown for 
(int II = 0; II < threadnum; ii++) {//Open Threadnum thread 
final iterator<string> ITT = It.get (ii); 
Thread t = new Importthread (itt,sql,threadsignal); 
T.start (); 
} 
Threadsignal.await ()//waits for all child threads to finish executing 
System.out.println (Thread.CurrentThread (). GetName () + "end."); /Print end tag 

Print results:

Main start
Thread-1 start ...
Thread-0 start ...
Thread-2 start ...
Thread-3 start ...
Thread-4 start ...
Thread-5 start ...
Thread-0 end. There are 5 other threads
Thread-1 end. There are 4 other threads
Thread-4 end. There are 3 other threads
Thread-2 end. There are 2 other threads
Thread-5 end. There are 1 other threads
Thread-3 end. There are 0 other threads
Main end.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.