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.