私の友人は、テキストドキュメントからOracleデータベースにデータをインポートするプログラムを作成するのを手伝ってくれるように頼みました。技術的には難しくありません。ドキュメントの形式は固定されています。データベース内の対応するフィールド分析で十分である限り、キーはパフォーマンスにあります。
データボリュームは大きく、数百万のレコードです。したがって、マルチスレッドの同時実行を使用する必要があり、執筆プロセス中に問題に遭遇する必要があることを考慮すると、実行が完了した後にすべての子プロセスに費やされた合計時間を数えたいと思います。最初の子プロセスが作成される前に現在の時間を記録します。 System.CurrentTimeMillis()を使用して、最後の子プロセスが完了した後の現在の時間を記録します。減算によって2回得られる時間差は、合計時間です。コードは次のとおりです
long tstart = system.currenttimemillis(); system.out.println(thread.currentthread()。getName() + "start"); //(int II = 0; ii <threadnum; ii ++){// open swreets runnable r = new runnable(){@Override public void run(){system.out.out.out.out.currentthread( //何かをする... ... System.out.println(thread.currentThread()。getName() + "end。"); }}スレッドt = newスレッド(r); t.start(); } system.out.println(thread.currentThread()。getName() + "end"); // end end long tend = system.currenttimemillis(); system.out.println( "合計時間:" +(tend -tstart) + "millions");その結果、メインスレッドが合計時間を印刷するために使用したステートメントは、ループが終了する瞬間に実行されます。その理由は、すべての子スレッドが同時に実行され、メインスレッドも実行されたときに実行されているためです。これは、「すべての子スレッドが実行されるのをメインスレッドに待つ方法」という疑問を提起します。各チャイルドスレッドが起動した後にT.join()を追加しようとしましたが、その結果、すべてのスレッドが順次実行され、これは並行性の意味を失います。これは明らかに私が望むものではありません。
Googleは長い間オンラインで解決策を見つけていません。誰もそのようなニーズに遭遇したことがありませんか?それとも、この問題は単純すぎますか?ウーナイは自分で解決策を考えなければなりませんでした...
最後に、私のソリューションは、java.lang.threadからemportthreadクラスをカスタマイズし、run()メソッドをオーバーロードし、リストプロパティを使用して生成されたすべてのスレッドを保存することです。このようにして、リストが空であるかどうかを判断する限り、実行されていない子スレッドがまだあるかどうかがわかります。クラスコードは次のとおりです。
public class importthreadはスレッド{private static list <shood> runningthreads = new ArrayList <thread>(); public Importthread(){} @Override public void run(){登録(this); // register system.out.println(thread.currentthread()。getName() + "start ..."); "end。"); // end tagを印刷} public void登録(スレッドT){synchronized(runningthreads){runningthreads.add(t); }} public void unregist(thread t){synchronized(runningthreads){synchronized(runningthreads){runningthreads.remove(t); }} public static boolean hasthreadrunning(){return(runningthreads.size()> 0); // runningthreadsが空であるかどうかを判断することにより、実行されていないスレッドがまだあるかどうかを知ることができます}}}}メインスレッドのコード:
long tstart = system.currenttimemillis(); system.out.println(thread.currentthread()。getName()+"start"); //(int ii = 0; ii <threadnum; ii ++){// open threads thread t = new importthread(); t.start(); } while(true){//すべてのチャイルドスレッドが実行を完了するのを待っていますif(!importthread.hasthreadrunning()){break; } thread.sleep(500); } system.out.println(thread.currentThread()。getName() + "end"); // end end long tend = system.currenttimemillis(); system.out.println( "合計時間:" +(tend -tstart) + "millions");印刷の結果は次のとおりです。
メインスタート
スレッド1が始まります...
スレッド5が始まります...
スレッド-0が始まります...
スレッド2が始まります...
スレッド3が始まります...
スレッド4が始まります...
スレッド5は終了します。
スレッド4は終了します。
スレッド2は終了します。
スレッド0は終了します。
スレッド3は終了します。
スレッド1は終了します。
メインの終わり。
合計時間:20860百万
メインスレッドは、すべての子スレッドが実行された後にのみ実行を開始することがわかります。
=========================================================================== ==============================================================================
上記の方法には隠された危険があります。スレッド1が開始および終了し、他のスレッドがまだ開始されていない場合、runningThreadsのサイズも0です。メインスレッドは、すべてのスレッドが実行されていると考えます。解決策は、リストタイプRunningThreadsを非シンプルタイプカウンターに置き換えることであり、スレッドの作成前にカウンター値を設定する必要があります。
MyCountDownクラス
パブリッククラス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クラス
パブリッククラスImportThreadはスレッドを拡張します{private mycountdown c; public importthread(mycountdown c){this.c = c; } @Override public void run(){system.out.println(thread.currentthread()。getname() + "start ..."); // start marker // do something c.countdown(); // do c.countdown(); // system.out.println(thread.currentthread()。エンドマーク}}メインスレッドで
system.out.println(thread.currentthread()。getName()+"start"); // startタグmycountdown c = new mycountdown(threadnum); //(int ii = 0; ii ++){//オープンスレッドスレッドt = new importthread(c); t.start(); } while(true){//すべての子スレッドがif(!c.hasnext())breakを実行するのを待っています。 } system.out.println(thread.currentthread()。getName() + "end。"); // end markを印刷します印刷結果:
メインスタート
スレッド2が始まります...
スレッド1が始まります...
スレッド-0が始まります...
スレッド3が始まります...
スレッド5が始まります...
スレッド4が始まります...
スレッド5は終了します。さらに5つのスレッド
スレッド1は終了します。さらに4つのスレッドがあります
スレッド4は終了します。さらに3つのスレッドがあります
スレッド2は終了します。さらに2つのスレッド
スレッド3は終了します。 1つのスレッドはまだそこにあります
スレッド0は終了します。残りの0本のスレッドがあります
メインの終わり。
より簡単な方法:java.util.concurrent.countdownlatchを使用するmycountdownの代わりに、(true){...}の代わりにawait()メソッドを使用します。
ImportThreadクラス
public class ImportThreadはスレッドを拡張します{private countdownLatchスレッドSsignal; public ImportThread(CountDownLatch ThreadsSignal){this.threadssignal = threadssignal; } @Override public void run(){system.out.println(thread.currentthread()。getname() + "start ..."); // shoodssignal.countdown(); //スレッドSystem.out.println(thread.currentthread()。getName() + "end。" + threadssignal.getcount() + "swreps"); }}メインスレッドで
CountDownLatch ThreadSignal = new CountDownLatch(threadnum); //(int ii = 0; ii <threadnum; ii ++){// open threads final Iterator <string> itt = it.get(ii);スレッドT = new ImportThread(ITT、SQL、ThreadSignal); t.start(); } threadsignal.await(); //すべてのチャイルドスレッドが実行system.out.println(thread.currentthread()。getname() + "end"); // end markを印刷するのを完了するのを待っています。印刷結果:
メインスタート
スレッド1が始まります...
スレッド-0が始まります...
スレッド2が始まります...
スレッド3が始まります...
スレッド4が始まります...
スレッド5が始まります...
スレッド0は終了します。さらに5つのスレッド
スレッド1は終了します。さらに4つのスレッドがあります
スレッド4は終了します。さらに3つのスレッドがあります
スレッド2は終了します。さらに2つのスレッド
スレッド5は終了します。 1つのスレッドはまだそこにあります
スレッド3は終了します。残りの0本のスレッドがあります
メインの終わり。
上記はこの記事のすべての内容です。私はそれがすべての人の学習に役立つことを願っています、そして、私は誰もがwulin.comをもっとサポートすることを願っています。