My friend asked me to help me write a program to import data from a text document into an oracle database. It is not technically difficult. The format of the document is fixed. As long as the corresponding field analysis in the database is enough, the key lies in performance.
The data volume is very large and millions of records. Therefore, considering that you need to use multi-thread concurrent execution, you encounter problems during the writing process. I want to count the total time spent on all child processes after the execution is completed. Record the current time before the first child process is created. Use () to record the current time after the last child process is completed. The time difference obtained by subtraction twice is the total time. The code is as follows.
long tStart = (); (().getName() + "start");//Print start markfor (int ii = 0; ii < threadNum; ii++) {//Open threadNum threadRunnable r = new Runnable(){ @Override public void run(){ (().getName() + "start"); //Do something...(().getName() + "Finish."); } } Thread t = new Thread(r); (); } (().getName() + "Finish.");//Print end marklong tEnd = (); ("Total time:"+ (tEnd - tStart) + "millions");
The result is that the statement that the main thread prints the total time is executed almost the moment the for loop ends. The reason is that all the child threads are executed concurrently, and the main thread is also running when they run, which raises a question: how to "make the main thread wait for all the child threads to execute." I tried adding() after each child thread starts, and the result is that all threads are executed sequentially, which loses the meaning of concurrency, which is obviously not what I want.
Google hasn't found a solution online for a long time. Has no one ever encountered such a need? Or is this problem too simple? Wu Nai had to think of a solution...
Finally, my solution is to customize an ImportThread class inherited from, overload the run() method, and use a List property to save all generated threads. In this way, as long as you judge whether the List is empty, you will know whether there are still child threads that have not been 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);//Register at the beginning of thread(().getName() + "start...");//Print start mark//Do something...unRegist(this);//Unregister at the end of the thread(().getName() + "Finish.");//Print end mark} public void regist(Thread t){ synchronized(runningThreads){ (t); } } public void unRegist(Thread t){ synchronized(runningThreads){ (t); } } public static boolean hasThreadRunning() { return (() > 0);//By judging whether runningThreads is empty, you can know whether there are still threads that have not completed execution} }
Code in main thread:
long tStart = (); (().getName() + "start");//Print start markfor (int ii = 0; ii < threadNum; ii++) {//Open threadNum threadThread t = new ImportThread(); (); } while(true){//Waiting for all child threads to complete executionif(!()){ break; } (500); } (().getName() + "Finish.");//Print end marklong tEnd = (); ("Total time:"+ (tEnd - tStart) + "millions");
The printing results are:
Main Start
Thread-1 starts...
Thread-5 starts...
Thread-0 starts...
Thread-2 starts...
Thread-3 starts...
Thread-4 starts...
Thread-5 ends.
Thread-4 ends.
Thread-2 ends.
Thread-0 ends.
Thread-3 ends.
Thread-1 ends.
Main ends.
Total time: 20860millions
You can see that the main thread only starts execution after all the child threads are executed.
=================================================================================================
The above method has a hidden danger: if thread 1 starts and ends, and other threads have not started yet, the size of runningThreads is also 0, the main thread will think that all threads have been executed. The solution is to replace List type runningThreads with a non-simple type counter, and the counter value should be set before the thread is created.
MyCountDown class
public class MyCountDown { private int count; public MyCountDown(int count){ = count; } public synchronized void countDown(){ count--; } public synchronized boolean hasNext(){ return (count > 0); } public int getCount() { return count; } public void setCount(int count) { = count; } }
ImportThread class
public class ImportThread extends Thread { private MyCountDown c; public ImportThread(MyCountDown c) { = c; } @Override public void run() { (().getName() + "start...");//Print start mark//Do something ();//Timer minus 1(().getName() + "End. And" + () + "Threads");//Print end mark} }
In the main thread
(().getName() + "start");//Print start markMyCountDown c = new MyCountDown(threadNum);//Initialize countDownfor (int ii = 0; ii < threadNum; ii++) {//Open threadNum threadThread t = new ImportThread(c); (); } while(true){//Waiting for all child threads to complete executionif(!()) break; } (().getName() + "Finish.");//Print end mark
Print result:
Main Start
Thread-2 starts...
Thread-1 starts...
Thread-0 starts...
Thread-3 starts...
Thread-5 starts...
Thread-4 starts...
Thread-5 ends. There are 5 threads left
Thread-1 ends. There are 4 threads left
Thread-4 ends. There are 3 threads left
Thread-2 ends. There are 2 threads left
Thread-3 ends. There is 1 thread left
Thread-0 ends. There are 0 threads left
Main ends.
Easier way: use instead of MyCountDown, use await() method instead of while(true){...}
ImportThread class
public class ImportThread extends Thread { private CountDownLatch threadsSignal; public ImportThread(CountDownLatch threadsSignal) { = threadsSignal; } @Override public void run() { (().getName() + "start..."); //Do somethings ();//The counter is reduced by 1 when the thread is finished(().getName() + "End. And" + () + "Threads"); } }
In the main thread
CountDownLatch threadSignal = new CountDownLatch(threadNum);//Initialize countDownfor (int ii = 0; ii < threadNum; ii++) {//Open threadNum threadfinal Iterator<String> itt = (ii); Thread t = new ImportThread(itt,sql,threadSignal); (); } ();//Waiting for all child threads to complete execution(().getName() + "Finish.");//Print end mark
Print result:
Main Start
Thread-1 starts...
Thread-0 starts...
Thread-2 starts...
Thread-3 starts...
Thread-4 starts...
Thread-5 starts...
Thread-0 ends. There are 5 threads left
Thread-1 ends. There are 4 threads left
Thread-4 ends. There are 3 threads left
Thread-2 ends. There are 2 threads left
Thread-5 ends. There is 1 thread left
Thread-3 ends. There are 0 threads left
The end of main.
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.